1 65 66 67 package org.hsqldb; 68 69 import java.io.IOException ; 70 71 import org.hsqldb.HsqlNameManager.HsqlName; 72 import org.hsqldb.index.RowIterator; 73 import org.hsqldb.lib.ArrayUtil; 74 import org.hsqldb.lib.HashMappedList; 75 import org.hsqldb.lib.HashSet; 76 import org.hsqldb.lib.HsqlArrayList; 77 import org.hsqldb.lib.Iterator; 78 import org.hsqldb.lib.StringUtil; 79 import org.hsqldb.persist.CachedObject; 80 import org.hsqldb.persist.DataFileCache; 81 import org.hsqldb.persist.PersistentStore; 82 import org.hsqldb.rowio.RowInputInterface; 83 import org.hsqldb.store.ValuePool; 84 85 109 119 public class Table extends BaseTable { 120 121 public static final int SYSTEM_TABLE = 0; 123 public static final int SYSTEM_SUBQUERY = 1; 124 public static final int TEMP_TABLE = 2; 125 public static final int MEMORY_TABLE = 3; 126 public static final int CACHED_TABLE = 4; 127 public static final int TEMP_TEXT_TABLE = 5; 128 public static final int TEXT_TABLE = 6; 129 public static final int VIEW = 7; 130 131 static final int SYSTEM_VIEW = 8; 133 134 public HashMappedList columnList; private int[] primaryKeyCols; private int[] primaryKeyTypes; private int[] primaryKeyColsSequence; int[] bestRowIdentifierCols; boolean bestRowIdentifierStrict; int[] bestIndexForColumn; Index bestIndex; int identityColumn; NumberSequence identitySequence; NumberSequence rowIdSequence; 148 Constraint[] constraintList; HsqlArrayList[] triggerLists; private int[] colTypes; private int[] colSizes; private int[] colScales; private boolean[] colNullable; private Expression[] colDefaults; private int[] defaultColumnMap; private boolean hasDefaultValues; boolean sqlEnforceSize; 160 protected int columnCount; public Database database; 163 protected DataFileCache cache; 164 protected HsqlName tableName; private int tableType; 166 protected boolean isReadOnly; 167 protected boolean isTemp; 168 protected boolean isCached; 169 protected boolean isText; 170 protected boolean isMemory; 171 private boolean isView; 172 protected boolean isLogged; 173 protected int indexType; protected boolean onCommitPreserve; 176 PersistentStore rowStore; 178 Index[] indexList; 180 189 Table(Database db, HsqlName name, int type) throws HsqlException { 190 191 database = db; 192 sqlEnforceSize = db.sqlEnforceStrictSize; 193 identitySequence = new NumberSequence(null, 0, 1, Types.BIGINT); 194 rowIdSequence = new NumberSequence(null, 0, 1, Types.BIGINT); 195 196 switch (type) { 197 198 case SYSTEM_SUBQUERY : 199 isTemp = true; 200 isMemory = true; 201 case SYSTEM_TABLE : 202 isMemory = true; 203 break; 204 205 case CACHED_TABLE : 206 if (DatabaseURL.isFileBasedDatabaseType(db.getType())) { 207 cache = db.logger.getCache(); 208 isCached = true; 209 isLogged = !database.isFilesReadOnly(); 210 indexType = Index.DISK_INDEX; 211 rowStore = new RowStore(); 212 213 break; 214 } 215 216 type = MEMORY_TABLE; 217 case MEMORY_TABLE : 218 isMemory = true; 219 isLogged = !database.isFilesReadOnly(); 220 break; 221 222 case TEMP_TABLE : 223 isMemory = true; 224 isTemp = true; 225 break; 226 227 case TEMP_TEXT_TABLE : 228 if (!DatabaseURL.isFileBasedDatabaseType(db.getType())) { 229 throw Trace.error(Trace.DATABASE_IS_MEMORY_ONLY); 230 } 231 232 isTemp = true; 233 isText = true; 234 isReadOnly = true; 235 indexType = Index.POINTER_INDEX; 236 rowStore = new RowStore(); 237 break; 238 239 case TEXT_TABLE : 240 if (!DatabaseURL.isFileBasedDatabaseType(db.getType())) { 241 throw Trace.error(Trace.DATABASE_IS_MEMORY_ONLY); 242 } 243 244 isText = true; 245 indexType = Index.POINTER_INDEX; 246 rowStore = new RowStore(); 247 break; 248 249 case VIEW : 250 case SYSTEM_VIEW : 251 isView = true; 252 break; 253 } 254 255 tableType = type; 257 tableName = name; 258 primaryKeyCols = null; 259 primaryKeyTypes = null; 260 identityColumn = -1; 261 columnList = new HashMappedList(); 262 indexList = new Index[0]; 263 constraintList = new Constraint[0]; 264 triggerLists = new HsqlArrayList[TriggerDef.NUM_TRIGS]; 265 266 if (db.isFilesReadOnly() && isFileBased()) { 270 this.isReadOnly = true; 271 } 272 273 } 275 276 boolean equals(Session session, String name) { 277 278 284 return (tableName.name.equals(name)); 285 } 286 287 boolean equals(String name) { 288 return (tableName.name.equals(name)); 289 } 290 291 boolean equals(HsqlName name) { 292 return (tableName.equals(name)); 293 } 294 295 public final boolean isText() { 296 return isText; 297 } 298 299 public final boolean isTemp() { 300 return isTemp; 301 } 302 303 public final boolean isReadOnly() { 304 return isReadOnly; 305 } 306 307 final boolean isView() { 308 return isView; 309 } 310 311 final int getIndexType() { 312 return indexType; 313 } 314 315 public final int getTableType() { 316 return tableType; 317 } 318 319 public final boolean isDataReadOnly() { 320 return isReadOnly; 321 } 322 323 326 void checkDataReadOnly() throws HsqlException { 327 328 if (isReadOnly) { 329 throw Trace.error(Trace.DATA_IS_READONLY); 330 } 331 } 332 333 void setDataReadOnly(boolean value) throws HsqlException { 336 337 if (!value && database.isFilesReadOnly() && isFileBased()) { 340 throw Trace.error(Trace.DATA_IS_READONLY); 341 } 342 343 isReadOnly = value; 344 } 345 346 349 boolean isFileBased() { 350 return isCached || isText; 351 } 352 353 356 protected void setDataSource(Session s, String source, boolean isDesc, 357 boolean newFile) throws HsqlException { 358 throw (Trace.error(Trace.TABLE_NOT_FOUND)); 359 } 360 361 364 protected String getDataSource() { 365 return null; 366 } 367 368 371 protected boolean isDescDataSource() { 372 return false; 373 } 374 375 378 public void setHeader(String header) throws HsqlException { 379 throw Trace.error(Trace.TEXT_TABLE_HEADER); 380 } 381 382 385 public String getHeader() { 386 return null; 387 } 388 389 392 void addConstraint(Constraint c) { 393 394 constraintList = 395 (Constraint[]) ArrayUtil.toAdjustedArray(constraintList, c, 396 constraintList.length, 1); 397 } 398 399 402 void addPKConstraint(Constraint c) { 403 constraintList = 404 (Constraint[]) ArrayUtil.toAdjustedArray(constraintList, c, 0, 1); 405 } 406 407 410 Constraint[] getConstraints() { 411 return constraintList; 412 } 413 414 417 Constraint getPrimaryConstraint() { 418 return primaryKeyCols.length == 0 ? null 419 : constraintList[0]; 420 } 421 422 424 425 429 Index getUniqueConstraintIndexForColumns(int[] col) { 430 431 if (ArrayUtil.areEqual(getPrimaryIndex().getColumns(), col, 432 col.length, true)) { 433 return getPrimaryIndex(); 434 } 435 436 for (int i = 0, size = constraintList.length; i < size; i++) { 437 Constraint c = constraintList[i]; 438 439 if (c.getType() != Constraint.UNIQUE) { 440 continue; 441 } 442 443 if (ArrayUtil.areEqual(c.getMainColumns(), col, col.length, 444 true)) { 445 return c.getMainIndex(); 446 } 447 } 448 449 return null; 450 } 451 452 455 Constraint getConstraintForColumns(Table tablemain, int[] colmain, 456 int[] colref) { 457 458 for (int i = 0, size = constraintList.length; i < size; i++) { 459 Constraint c = constraintList[i]; 460 461 if (c.isEquivalent(tablemain, colmain, this, colref)) { 462 return c; 463 } 464 } 465 466 return null; 467 } 468 469 472 Constraint getUniqueConstraintForColumns(int[] cols) { 473 474 for (int i = 0, size = constraintList.length; i < size; i++) { 475 Constraint c = constraintList[i]; 476 477 if (c.isEquivalent(cols, Constraint.UNIQUE)) { 478 return c; 479 } 480 } 481 482 return null; 483 } 484 485 491 Constraint getUniqueOrPKConstraintForIndex(Index index) { 492 493 for (int i = 0, size = constraintList.length; i < size; i++) { 494 Constraint c = constraintList[i]; 495 496 if (c.getMainIndex() == index 497 && (c.getType() == Constraint.UNIQUE 498 || c.getType() == Constraint.PRIMARY_KEY)) { 499 return c; 500 } 501 } 502 503 return null; 504 } 505 506 513 int getNextConstraintIndex(int from, int type) { 514 515 for (int i = from, size = constraintList.length; i < size; i++) { 516 Constraint c = constraintList[i]; 517 518 if (c.getType() == type) { 519 return i; 520 } 521 } 522 523 return -1; 524 } 525 526 528 532 void addColumn(Column column) throws HsqlException { 533 534 if (findColumn(column.columnName.name) >= 0) { 535 throw Trace.error(Trace.COLUMN_ALREADY_EXISTS); 536 } 537 538 if (column.isIdentity()) { 539 Trace.check( 540 column.getType() == Types.INTEGER 541 || column.getType() == Types.BIGINT, Trace.WRONG_DATA_TYPE, 542 column.columnName.name); 543 Trace.check(identityColumn == -1, Trace.SECOND_PRIMARY_KEY, 544 column.columnName.name); 545 546 identityColumn = columnCount; 547 } 548 549 if (primaryKeyCols != null) { 550 Trace.doAssert(false, "Table.addColumn"); 551 } 552 553 columnList.add(column.columnName.name, column); 554 555 columnCount++; 556 } 557 558 561 void addColumns(Result.ResultMetaData metadata, 562 int count) throws HsqlException { 563 564 for (int i = 0; i < count; i++) { 565 Column column = new Column( 566 database.nameManager.newHsqlName( 567 metadata.colLabels[i], metadata.isLabelQuoted[i]), true, 568 metadata.colTypes[i], metadata.colSizes[i], 569 metadata.colScales[i], false, null); 570 571 addColumn(column); 572 } 573 } 574 575 578 void addColumns(Select select) throws HsqlException { 579 580 int colCount = select.iResultLen; 581 582 for (int i = 0; i < colCount; i++) { 583 Expression e = select.exprColumns[i]; 584 Column column = new Column( 585 database.nameManager.newHsqlName( 586 e.getAlias(), e.isAliasQuoted()), true, e.getDataType(), 587 e.getColumnSize(), e.getColumnScale(), false, null); 588 589 addColumn(column); 590 } 591 } 592 593 596 public HsqlName getName() { 597 return tableName; 598 } 599 600 public int getId() { 601 return tableName.hashCode(); 602 } 603 604 609 void rename(Session session, String newname, 610 boolean isquoted) throws HsqlException { 611 612 String oldname = tableName.name; 613 614 tableName.rename(newname, isquoted); 615 616 if (HsqlName.isReservedIndexName(getPrimaryIndex().getName().name)) { 617 getPrimaryIndex().getName().rename("SYS_PK", newname, isquoted); 618 } 619 620 renameTableInCheckConstraints(session, oldname, newname); 621 } 622 623 626 int getInternalColumnCount() { 627 return columnCount; 628 } 629 630 633 protected Table duplicate() throws HsqlException { 634 635 Table t = (new Table(database, tableName, tableType)); 636 637 return t; 638 } 639 640 648 void checkColumnsMatch(int[] col, Table other, 649 int[] othercol) throws HsqlException { 650 651 if (col.length != othercol.length) { 652 throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH); 653 } 654 655 for (int i = 0; i < col.length; i++) { 656 657 if (col[i] >= columnCount || othercol[i] >= other.columnCount) { 659 throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH); 660 } 661 662 if (getColumn(col[i]).getType() 663 != other.getColumn(othercol[i]).getType()) { 664 throw Trace.error(Trace.COLUMN_TYPE_MISMATCH); 665 } 666 } 667 } 668 669 671 679 Table moveDefinition(int[] removeIndex, Column newColumn, int colIndex, 680 int adjust) throws HsqlException { 681 682 Table tn = duplicate(); 683 684 for (int i = 0; i < columnCount + 1; i++) { 687 if (i == colIndex) { 688 if (adjust == 0) { 689 if (newColumn != null) { 690 tn.addColumn(newColumn); 691 692 continue; 693 } 694 } else if (adjust > 0) { 695 tn.addColumn(newColumn); 696 } else if (adjust < 0) { 697 continue; 698 } 699 } 700 701 if (i == columnCount) { 702 break; 703 } 704 705 tn.addColumn(getColumn(i)); 706 } 707 708 int[] primarykey = primaryKeyCols.length == 0 ? null 710 : primaryKeyCols; 711 712 if (primarykey != null) { 713 int[] newpk = ArrayUtil.toAdjustedColumnArray(primarykey, 714 colIndex, adjust); 715 716 if (primarykey.length != newpk.length) { 717 throw Trace.error(Trace.DROP_PRIMARY_KEY); 718 } else { 719 primarykey = newpk; 720 } 721 } 722 723 tn.createPrimaryKey(getIndex(0).getName(), primarykey, false); 724 725 tn.constraintList = constraintList; 726 727 Index idx = null; 728 729 if (removeIndex != null) { 730 idx = getIndex(removeIndex, colIndex); 731 } 732 733 if (idx != null) { 734 if (idx.isConstraint()) { 735 throw Trace.error(Trace.COLUMN_IS_IN_CONSTRAINT); 736 } else { 737 throw Trace.error(Trace.COLUMN_IS_IN_INDEX); 738 } 739 } 740 741 for (int i = 1; i < indexList.length; i++) { 742 if (removeIndex != null && ArrayUtil.find(removeIndex, i) != -1) { 743 continue; 744 } 745 746 tn.createAdjustedIndex(indexList[i], colIndex, adjust); 747 } 748 749 tn.triggerLists = triggerLists; 750 751 return tn; 752 } 753 754 Index getIndex(int[] exclude, int colIndex) { 755 756 for (int i = 1; i < indexList.length; i++) { 757 if (exclude != null && ArrayUtil.find(exclude, i) != -1) { 758 continue; 759 } 760 761 Index idx = indexList[i]; 762 int[] cols = idx.getColumns(); 763 764 if (ArrayUtil.find(cols, colIndex) != -1) { 765 return idx; 766 } 767 } 768 769 return null; 770 } 771 772 private void copyIndexes(Table tn, int removeIndex, int colIndex, 773 int adjust) throws HsqlException { 774 775 for (int i = 1; i < getIndexCount(); i++) { 776 Index idx = indexList[i]; 777 778 if (removeIndex == i) { 779 continue; 780 } 781 782 Index newidx = tn.createAdjustedIndex(idx, colIndex, adjust); 783 784 if (newidx == null) { 785 786 throw Trace.error(Trace.COLUMN_IS_IN_INDEX); 788 } 789 } 790 } 791 792 795 Table moveDefinitionPK(int[] pkCols, 796 boolean withIdentity) throws HsqlException { 797 798 if ((hasPrimaryKey() && pkCols != null) 800 || (!hasPrimaryKey() && pkCols == null)) { 801 throw Trace.error(Trace.DROP_PRIMARY_KEY); 802 } 803 804 Table tn = duplicate(); 805 806 for (int i = 0; i < columnCount; i++) { 807 tn.addColumn(getColumn(i).duplicate(withIdentity)); 808 } 809 810 tn.createPrimaryKey(getIndex(0).getName(), pkCols, true); 811 812 tn.constraintList = constraintList; 813 814 for (int i = 1; i < getIndexCount(); i++) { 815 Index idx = getIndex(i); 816 817 tn.createAdjustedIndex(idx, -1, 0); 818 } 819 820 tn.triggerLists = triggerLists; 821 822 return tn; 823 } 824 825 829 void updateConstraintsTables(Session session, Table old, int colindex, 830 int adjust) throws HsqlException { 831 832 for (int i = 0, size = constraintList.length; i < size; i++) { 833 Constraint c = constraintList[i]; 834 835 c.replaceTable(old, this, colindex, adjust); 836 837 if (c.constType == Constraint.CHECK) { 838 recompileCheckConstraint(session, c); 839 } 840 } 841 } 842 843 private void recompileCheckConstraints(Session session) 844 throws HsqlException { 845 846 for (int i = 0, size = constraintList.length; i < size; i++) { 847 Constraint c = constraintList[i]; 848 849 if (c.constType == Constraint.CHECK) { 850 recompileCheckConstraint(session, c); 851 } 852 } 853 } 854 855 858 private void recompileCheckConstraint(Session session, 859 Constraint c) throws HsqlException { 860 861 String ddl = c.core.check.getDDL(); 862 Tokenizer tokenizer = new Tokenizer(ddl); 863 Parser parser = new Parser(session, database, tokenizer); 864 Expression condition = parser.parseExpression(); 865 866 c.core.check = condition; 867 868 condition.setLikeOptimised(); 870 871 Select s = Expression.getCheckSelect(session, this, condition); 872 873 c.core.checkFilter = s.tFilter[0]; 874 875 c.core.checkFilter.setAsCheckFilter(); 876 877 c.core.mainTable = this; 878 } 879 880 883 void checkColumnInCheckConstraint(String colname) throws HsqlException { 884 885 for (int i = 0, size = constraintList.length; i < size; i++) { 886 Constraint c = constraintList[i]; 887 888 if (c.constType == Constraint.CHECK) { 889 if (c.hasColumn(this, colname)) { 890 throw Trace.error(Trace.COLUMN_IS_REFERENCED, 891 c.getName()); 892 } 893 } 894 } 895 } 896 897 902 void checkColumnInFKConstraint(int colIndex) throws HsqlException { 903 904 for (int i = 0, size = constraintList.length; i < size; i++) { 905 Constraint c = constraintList[i]; 906 907 if (c.hasColumn(colIndex) 908 && (c.getType() == Constraint.MAIN 909 || c.getType() == Constraint.FOREIGN_KEY)) { 910 throw Trace.error(Trace.COLUMN_IS_REFERENCED, 911 c.getName().name); 912 } 913 } 914 } 915 916 921 void checkColumnInFKConstraint(int colIndex, 922 int actionType) throws HsqlException { 923 924 for (int i = 0, size = constraintList.length; i < size; i++) { 925 Constraint c = constraintList[i]; 926 927 if (c.hasColumn(colIndex)) { 928 if (c.getType() == Constraint.FOREIGN_KEY 929 && (actionType == c.getUpdateAction() 930 || actionType == c.getDeleteAction())) { 931 throw Trace.error(Trace.COLUMN_IS_REFERENCED, 932 c.getName().name); 933 } 934 } 935 } 936 } 937 938 941 private void renameColumnInCheckConstraints(String oldname, 942 String newname, boolean isquoted) throws HsqlException { 943 944 for (int i = 0, size = constraintList.length; i < size; i++) { 945 Constraint c = constraintList[i]; 946 947 if (c.constType == Constraint.CHECK) { 948 Expression.Collector coll = new Expression.Collector(); 949 950 coll.addAll(c.core.check, Expression.COLUMN); 951 952 Iterator it = coll.iterator(); 953 954 for (; it.hasNext(); ) { 955 Expression e = (Expression) it.next(); 956 957 if (e.getColumnName() == oldname) { 958 e.setColumnName(newname, isquoted); 959 } 960 } 961 } 962 } 963 } 964 965 968 private void renameTableInCheckConstraints(Session session, 969 String oldname, String newname) throws HsqlException { 970 971 for (int i = 0, size = constraintList.length; i < size; i++) { 972 Constraint c = constraintList[i]; 973 974 if (c.constType == Constraint.CHECK) { 975 Expression.Collector coll = new Expression.Collector(); 976 977 coll.addAll(c.core.check, Expression.COLUMN); 978 979 Iterator it = coll.iterator(); 980 981 for (; it.hasNext(); ) { 982 Expression e = (Expression) it.next(); 983 984 if (e.getTableName() == oldname) { 985 e.setTableName(newname); 986 } 987 } 988 } 989 } 990 991 recompileCheckConstraints(session); 992 } 993 994 997 public int getColumnCount() { 998 return columnCount; 999 } 1000 1001 1004 public int getIndexCount() { 1005 return indexList.length; 1006 } 1007 1008 1011 int getIdentityColumn() { 1012 return identityColumn; 1013 } 1014 1015 1018 int getColumnNr(String c) throws HsqlException { 1019 1020 int i = findColumn(c); 1021 1022 if (i == -1) { 1023 throw Trace.error(Trace.COLUMN_NOT_FOUND, c); 1024 } 1025 1026 return i; 1027 } 1028 1029 1032 int findColumn(String c) { 1033 1034 int index = columnList.getIndex(c); 1035 1036 return index; 1037 } 1038 1039 1042 public Index getPrimaryIndex() { 1043 return getIndex(0); 1044 } 1045 1046 1049 public int[] getPrimaryKey() { 1050 return primaryKeyCols; 1051 } 1052 1053 public int[] getPrimaryKeyTypes() { 1054 return primaryKeyTypes; 1055 } 1056 1057 public boolean hasPrimaryKey() { 1058 return !(primaryKeyCols.length == 0); 1059 } 1060 1061 int[] getBestRowIdentifiers() { 1062 return bestRowIdentifierCols; 1063 } 1064 1065 boolean isBestRowIdentifiersStrict() { 1066 return bestRowIdentifierStrict; 1067 } 1068 1069 1087 void setBestRowIdentifiers() { 1088 1089 int[] briCols = null; 1090 int briColsCount = 0; 1091 boolean isStrict = false; 1092 int nNullCount = 0; 1093 1094 if (colNullable == null) { 1096 return; 1097 } 1098 1099 bestIndex = null; 1100 bestIndexForColumn = new int[columnList.size()]; 1101 1102 ArrayUtil.fillArray(bestIndexForColumn, -1); 1103 1104 for (int i = 0; i < indexList.length; i++) { 1105 Index index = indexList[i]; 1106 int[] cols = index.getColumns(); 1107 int colsCount = index.getVisibleColumns(); 1108 1109 if (i == 0) { 1110 1111 if (hasPrimaryKey()) { 1113 isStrict = true; 1114 } else { 1115 continue; 1116 } 1117 } 1118 1119 if (bestIndexForColumn[cols[0]] == -1) { 1120 bestIndexForColumn[cols[0]] = i; 1121 } 1122 1123 if (!index.isUnique()) { 1124 if (bestIndex == null) { 1125 bestIndex = index; 1126 } 1127 1128 continue; 1129 } 1130 1131 int nnullc = 0; 1132 1133 for (int j = 0; j < colsCount; j++) { 1134 if (!colNullable[cols[j]]) { 1135 nnullc++; 1136 } 1137 } 1138 1139 if (bestIndex != null) { 1140 bestIndex = index; 1141 } 1142 1143 if (nnullc == colsCount) { 1144 if (briCols == null || briColsCount != nNullCount 1145 || colsCount < briColsCount) { 1146 1147 briCols = cols; 1151 briColsCount = colsCount; 1152 nNullCount = colsCount; 1153 isStrict = true; 1154 } 1155 1156 continue; 1157 } else if (isStrict) { 1158 continue; 1159 } else if (briCols == null || colsCount < briColsCount 1160 || nnullc > nNullCount) { 1161 1162 briCols = cols; 1166 briColsCount = colsCount; 1167 nNullCount = nnullc; 1168 } 1169 } 1170 1171 bestRowIdentifierCols = briCols == null 1173 || briColsCount == briCols.length ? briCols 1174 : ArrayUtil 1175 .arraySlice(briCols, 1176 0, briColsCount); 1177 bestRowIdentifierStrict = isStrict; 1178 1179 if (hasPrimaryKey()) { 1180 bestIndex = getPrimaryIndex(); 1181 } 1182 } 1183 1184 1187 void setDefaultExpression(int columnIndex, Expression def) { 1188 1189 Column column = getColumn(columnIndex); 1190 1191 column.setDefaultExpression(def); 1192 1193 colDefaults[columnIndex] = column.getDefaultExpression(); 1194 1195 resetDefaultsFlag(); 1196 } 1197 1198 1201 void resetDefaultsFlag() { 1202 1203 hasDefaultValues = false; 1204 1205 for (int i = 0; i < columnCount; i++) { 1206 hasDefaultValues = hasDefaultValues || colDefaults[i] != null; 1207 } 1208 } 1209 1210 DataFileCache getCache() { 1211 return cache; 1212 } 1213 1214 1218 Index getIndexForColumn(Session session, int column) { 1219 1220 int i = bestIndexForColumn[column]; 1221 1222 if (i == -1 1223 && (tableType == Table.SYSTEM_SUBQUERY 1224 || tableType == Table.SYSTEM_TABLE)) { 1225 try { 1226 HsqlName indexName = database.nameManager.newAutoName("IDX"); 1227 1228 createIndex(session, new int[]{ column }, indexName, false, 1229 false, false); 1230 1231 i = bestIndexForColumn[column]; 1232 } catch (Exception e) {} 1233 } 1234 1235 return i == -1 ? null 1236 : getIndex(i); 1237 } 1238 1239 1242 Index getIndexForColumns(boolean[] columnCheck) { 1243 1244 Index indexChoice = null; 1245 int colCount = 0; 1246 1247 for (int i = 0; i < indexList.length; i++) { 1248 Index index = indexList[i]; 1249 boolean result = ArrayUtil.containsAllTrueElements(columnCheck, 1250 index.colCheck); 1251 1252 if (result && index.getVisibleColumns() > colCount) { 1253 colCount = index.getVisibleColumns(); 1254 indexChoice = index; 1255 } 1256 } 1257 1258 return indexChoice; 1259 } 1260 1261 1264 Index getIndexForColumns(int[] col, boolean unique) throws HsqlException { 1265 1266 for (int i = 0, count = getIndexCount(); i < count; i++) { 1267 Index currentindex = getIndex(i); 1268 int[] indexcol = currentindex.getColumns(); 1269 1270 if (ArrayUtil.haveEqualArrays(indexcol, col, col.length)) { 1271 if (!unique || currentindex.isUnique()) { 1272 return currentindex; 1273 } 1274 } 1275 } 1276 1277 return null; 1278 } 1279 1280 1284 public int[] getIndexRootsArray() { 1285 1286 int[] roots = new int[getIndexCount()]; 1287 1288 for (int i = 0; i < getIndexCount(); i++) { 1289 roots[i] = indexList[i].getRoot(); 1290 } 1291 1292 return roots; 1293 } 1294 1295 1300 String getIndexRoots() { 1301 1302 String roots = StringUtil.getList(getIndexRootsArray(), " ", ""); 1303 StringBuffer s = new StringBuffer (roots); 1304 1305 s.append(' '); 1306 s.append(identitySequence.peek()); 1307 1308 return s.toString(); 1309 } 1310 1311 1318 public void setIndexRoots(int[] roots) throws HsqlException { 1319 1320 Trace.check(isCached, Trace.TABLE_NOT_FOUND); 1321 1322 for (int i = 0; i < getIndexCount(); i++) { 1323 int p = roots[i]; 1324 Row r = null; 1325 1326 if (p != -1) { 1327 r = (CachedRow) rowStore.get(p); 1328 } 1329 1330 Node f = null; 1331 1332 if (r != null) { 1333 f = r.getNode(i); 1334 } 1335 1336 indexList[i].setRoot(null, f); 1337 } 1338 } 1339 1340 1343 void setIndexRoots(String s) throws HsqlException { 1344 1345 Trace.check(isCached, Trace.TABLE_NOT_FOUND); 1347 1348 Tokenizer t = new Tokenizer(s); 1349 int[] roots = new int[getIndexCount()]; 1350 1351 for (int i = 0; i < getIndexCount(); i++) { 1352 int v = t.getInt(); 1353 1354 roots[i] = v; 1355 } 1356 1357 setIndexRoots(roots); 1358 1359 long v = t.getBigint(); 1360 1361 identitySequence.reset(v); 1362 } 1363 1364 1367 void createPrimaryKey(int[] cols) throws HsqlException { 1368 createPrimaryKey(null, cols, false); 1369 } 1370 1371 1374 void createPrimaryKey() throws HsqlException { 1375 createPrimaryKey(null, null, false); 1376 } 1377 1378 1382 1383 void createPrimaryKey(HsqlName indexName, int[] columns, 1385 boolean columnsNotNull) throws HsqlException { 1386 1387 if (primaryKeyCols != null) { 1388 Trace.doAssert(false, "Table.createPrimaryKey(column)"); 1389 } 1390 1391 if (columns == null) { 1392 columns = new int[0]; 1393 } else { 1394 for (int i = 0; i < columns.length; i++) { 1395 if (columnsNotNull) { 1396 getColumn(columns[i]).setNullable(false); 1397 } 1398 1399 getColumn(columns[i]).setPrimaryKey(true); 1400 } 1401 } 1402 1403 primaryKeyCols = columns; 1404 colTypes = new int[columnCount]; 1405 colDefaults = new Expression[columnCount]; 1406 colSizes = new int[columnCount]; 1407 colScales = new int[columnCount]; 1408 colNullable = new boolean[columnCount]; 1409 defaultColumnMap = new int[columnCount]; 1410 1411 for (int i = 0; i < columnCount; i++) { 1412 setColumnTypeVars(i); 1413 } 1414 1415 primaryKeyTypes = new int[primaryKeyCols.length]; 1416 1417 ArrayUtil.copyColumnValues(colTypes, primaryKeyCols, primaryKeyTypes); 1418 1419 primaryKeyColsSequence = new int[primaryKeyCols.length]; 1420 1421 ArrayUtil.fillSequence(primaryKeyColsSequence); 1422 resetDefaultsFlag(); 1423 1424 HsqlName name = indexName != null ? indexName 1426 : database.nameManager.newAutoName( 1427 "IDX"); 1428 1429 createPrimaryIndex(columns, name); 1430 setBestRowIdentifiers(); 1431 } 1432 1433 void setColumnTypeVars(int i) { 1434 1435 Column column = getColumn(i); 1436 1437 colTypes[i] = column.getType(); 1438 colSizes[i] = column.getSize(); 1439 colScales[i] = column.getScale(); 1440 colNullable[i] = column.isNullable(); 1441 defaultColumnMap[i] = i; 1442 1443 if (column.isIdentity()) { 1444 identitySequence.reset(column.identityStart, 1445 column.identityIncrement); 1446 } 1447 1448 colDefaults[i] = column.getDefaultExpression(); 1449 } 1450 1451 HsqlName makeSysPKName() throws HsqlException { 1452 return database.nameManager.newAutoName("PK"); 1453 } 1454 1455 void createPrimaryIndex(int[] pkcols, 1456 HsqlName name) throws HsqlException { 1457 1458 int[] pkcoltypes = new int[pkcols.length]; 1459 1460 for (int j = 0; j < pkcols.length; j++) { 1461 pkcoltypes[j] = colTypes[pkcols[j]]; 1462 } 1463 1464 Index newindex = new Index(database, name, this, pkcols, pkcoltypes, 1465 true, true, true, false, pkcols, 1466 pkcoltypes, isTemp); 1467 1468 addIndex(newindex); 1469 } 1470 1471 1475 private Index createAdjustedIndex(Index index, int colindex, 1476 int adjust) throws HsqlException { 1477 1478 int[] indexcolumns = (int[]) ArrayUtil.resizeArray(index.getColumns(), 1479 index.getVisibleColumns()); 1480 int[] colarr = ArrayUtil.toAdjustedColumnArray(indexcolumns, 1481 colindex, adjust); 1482 1483 if (colarr.length != index.getVisibleColumns()) { 1485 return null; 1486 } 1487 1488 return createIndexStructure(colarr, index.getName(), 1489 index.isUnique(), index.isConstraint, 1490 index.isForward); 1491 } 1492 1493 1496 Index createIndex(Session session, int[] column, HsqlName name, 1497 boolean unique, boolean constraint, 1498 boolean forward) throws HsqlException { 1499 1500 int newindexNo = createIndexStructureGetNo(column, name, unique, 1501 constraint, forward); 1502 Index newindex = indexList[newindexNo]; 1503 Index primaryindex = getPrimaryIndex(); 1504 RowIterator it = primaryindex.firstRow(session); 1505 int rowCount = 0; 1506 HsqlException error = null; 1507 1508 try { 1509 while (it.hasNext()) { 1510 Row row = it.next(); 1511 Node backnode = row.getNode(newindexNo - 1); 1512 Node newnode = Node.newNode(row, newindexNo, this); 1513 1514 newnode.nNext = backnode.nNext; 1515 backnode.nNext = newnode; 1516 1517 rowCount++; 1519 1520 newindex.insert(session, row, newindexNo); 1521 } 1522 1523 return newindex; 1524 } catch (java.lang.OutOfMemoryError e) { 1525 error = Trace.error(Trace.OUT_OF_MEMORY); 1526 } catch (HsqlException e) { 1527 error = e; 1528 } 1529 1530 it = primaryindex.firstRow(session); 1533 1534 for (int i = 0; i < rowCount; i++) { 1535 Row row = it.next(); 1536 Node backnode = row.getNode(0); 1537 int j = newindexNo; 1538 1539 while (--j > 0) { 1540 backnode = backnode.nNext; 1541 } 1542 1543 backnode.nNext = backnode.nNext.nNext; 1544 } 1545 1546 indexList = (Index[]) ArrayUtil.toAdjustedArray(indexList, null, 1547 newindexNo, -1); 1548 1549 setBestRowIdentifiers(); 1550 1551 throw error; 1552 } 1553 1554 1557 Index createIndexStructure(int[] columns, HsqlName name, boolean unique, 1558 boolean constraint, 1559 boolean forward) throws HsqlException { 1560 1561 int i = createIndexStructureGetNo(columns, name, unique, constraint, 1562 forward); 1563 1564 return indexList[i]; 1565 } 1566 1567 int createIndexStructureGetNo(int[] column, HsqlName name, 1568 boolean unique, boolean constraint, 1569 boolean forward) throws HsqlException { 1570 1571 if (primaryKeyCols == null) { 1572 Trace.doAssert(false, "createIndex"); 1573 } 1574 1575 int s = column.length; 1576 int[] col = new int[s]; 1577 int[] type = new int[s]; 1578 1579 for (int j = 0; j < s; j++) { 1580 col[j] = column[j]; 1581 type[j] = colTypes[col[j]]; 1582 } 1583 1584 int[] pkcols = getPrimaryKey(); 1585 int[] pktypes = getPrimaryKeyTypes(); 1586 Index newindex = new Index(database, name, this, col, type, false, 1587 unique, constraint, forward, pkcols, 1588 pktypes, isTemp); 1589 int indexNo = addIndex(newindex); 1590 1591 setBestRowIdentifiers(); 1592 1593 return indexNo; 1594 } 1595 1596 private int addIndex(Index index) { 1597 1598 int i = 0; 1599 1600 for (; i < indexList.length; i++) { 1601 Index current = indexList[i]; 1602 int order = index.getIndexOrderValue() 1603 - current.getIndexOrderValue(); 1604 1605 if (order < 0) { 1606 break; 1607 } 1608 } 1609 1610 indexList = (Index[]) ArrayUtil.toAdjustedArray(indexList, index, i, 1611 1); 1612 1613 return i; 1614 } 1615 1616 1620 boolean isIndexingMutable() { 1621 return !isIndexCached(); 1622 } 1623 1624 1629 void checkDropIndex(String indexname, HashSet ignore, 1630 boolean dropPK) throws HsqlException { 1631 1632 Index index = this.getIndex(indexname); 1633 1634 if (index == null) { 1635 throw Trace.error(Trace.INDEX_NOT_FOUND, indexname); 1636 } 1637 1638 if (!dropPK && index.equals(getIndex(0))) { 1639 throw Trace.error(Trace.DROP_PRIMARY_KEY, indexname); 1640 } 1641 1642 for (int i = 0, size = constraintList.length; i < size; i++) { 1643 Constraint c = constraintList[i]; 1644 1645 if (ignore != null && ignore.contains(c)) { 1646 continue; 1647 } 1648 1649 if (c.isIndexFK(index)) { 1650 throw Trace.error(Trace.DROP_FK_INDEX, indexname); 1651 } 1652 1653 if (c.isIndexUnique(index)) { 1654 throw Trace.error(Trace.SYSTEM_INDEX, indexname); 1655 } 1656 } 1657 1658 return; 1659 } 1660 1661 1664 public boolean isEmpty(Session session) { 1665 1666 if (getIndexCount() == 0) { 1667 return true; 1668 } 1669 1670 return getIndex(0).isEmpty(session); 1671 } 1672 1673 1676 int[] getColumnMap() { 1677 return defaultColumnMap; 1678 } 1679 1680 1683 int[] getNewColumnMap() { 1684 return new int[columnCount]; 1685 } 1686 1687 1690 boolean[] getNewColumnCheckList() { 1691 return new boolean[columnCount]; 1692 } 1693 1694 1697 public Object [] getEmptyRowData() { 1698 return new Object [columnCount]; 1699 } 1700 1701 1707 Object [] getNewRowData(Session session, 1708 boolean[] exists) throws HsqlException { 1709 1710 Object [] data = new Object [columnCount]; 1711 int i; 1712 1713 if (exists != null && hasDefaultValues) { 1714 for (i = 0; i < columnCount; i++) { 1715 Expression def = colDefaults[i]; 1716 1717 if (exists[i] == false && def != null) { 1718 data[i] = def.getValue(session, colTypes[i]); 1719 } 1720 } 1721 } 1722 1723 return data; 1724 } 1725 1726 1731 void dropIndex(Session session, String indexname) throws HsqlException { 1732 1733 int todrop = getIndexIndex(indexname); 1735 1736 indexList = (Index[]) ArrayUtil.toAdjustedArray(indexList, null, 1737 todrop, -1); 1738 1739 setBestRowIdentifiers(); 1740 dropIndexFromRows(session, todrop); 1741 } 1742 1743 void dropIndexFromRows(Session session, int index) throws HsqlException { 1744 1745 RowIterator it = getPrimaryIndex().firstRow(session); 1746 1747 while (it.hasNext()) { 1748 Row row = it.next(); 1749 int i = index - 1; 1750 Node backnode = row.getNode(0); 1751 1752 while (i-- > 0) { 1753 backnode = backnode.nNext; 1754 } 1755 1756 backnode.nNext = backnode.nNext.nNext; 1757 } 1758 } 1759 1760 1765 void moveData(Session session, Table from, int colindex, 1766 int adjust) throws HsqlException { 1767 1768 Object colvalue = null; 1769 Column column = null; 1770 1771 if (adjust >= 0 && colindex != -1) { 1772 column = getColumn(colindex); 1773 colvalue = column.getDefaultValue(session); 1774 } 1775 1776 RowIterator it = from.getPrimaryIndex().firstRow(session); 1777 1778 while (it.hasNext()) { 1779 Row row = it.next(); 1780 Object [] o = row.getData(); 1781 Object [] data = getEmptyRowData(); 1782 1783 if (adjust == 0 && colindex != -1) { 1784 colvalue = Column.convertObject(session, o[colindex], 1785 column.getType(), 1786 column.getSize(), 1787 column.getScale()); 1788 } 1789 1790 ArrayUtil.copyAdjustArray(o, data, colvalue, colindex, adjust); 1791 setIdentityColumn(session, data); 1792 enforceNullConstraints(data); 1793 1794 Row newrow = newRow(data); 1795 1796 indexRow(session, newrow); 1797 } 1798 1799 from.drop(); 1800 } 1801 1802 1806 int insert(Session session, Result ins) throws HsqlException { 1807 1808 Record ni = ins.rRoot; 1809 int count = 0; 1810 1811 fireAll(session, Trigger.INSERT_BEFORE); 1812 1813 while (ni != null) { 1814 insertRow(session, ni.data); 1815 1816 ni = ni.next; 1817 1818 count++; 1819 } 1820 1821 fireAll(session, Trigger.INSERT_AFTER); 1822 1823 return count; 1824 } 1825 1826 1831 void insert(Session session, Object [] data) throws HsqlException { 1832 1833 fireAll(session, Trigger.INSERT_BEFORE); 1834 insertRow(session, data); 1835 fireAll(session, Trigger.INSERT_AFTER); 1836 } 1837 1838 1842 private void insertRow(Session session, 1843 Object [] data) throws HsqlException { 1844 1845 if (triggerLists[Trigger.INSERT_BEFORE_ROW] != null) { 1846 fireAll(session, Trigger.INSERT_BEFORE_ROW, null, data); 1847 } 1848 1849 setIdentityColumn(session, data); 1850 checkRowDataInsert(session, data); 1851 insertNoCheck(session, data); 1852 1853 if (triggerLists[Trigger.INSERT_AFTER_ROW] != null) { 1854 fireAll(session, Trigger.INSERT_AFTER_ROW, null, data); 1855 checkRowDataInsert(session, data); 1856 } 1857 } 1858 1859 1866 void insertIntoTable(Session session, 1867 Result result) throws HsqlException { 1868 1869 insertResult(session, result); 1870 1871 if (!isLogged) { 1872 return; 1873 } 1874 1875 Record r = result.rRoot; 1876 1877 while (r != null) { 1878 database.logger.writeInsertStatement(session, this, r.data); 1879 1880 r = r.next; 1881 } 1882 } 1883 1884 1889 private void insertNoCheck(Session session, 1890 Object [] data) throws HsqlException { 1891 1892 Row row = newRow(data); 1893 1894 indexRow(session, row); 1896 1897 if (session != null) { 1898 session.addInsertAction(this, row); 1899 } 1900 1901 if (isLogged) { 1902 database.logger.writeInsertStatement(session, this, data); 1903 } 1904 } 1905 1906 1909 public void insertNoCheckFromLog(Session session, 1910 Object [] data) throws HsqlException { 1911 1912 Row r = newRow(data); 1913 1914 updateIdentityValue(data); 1915 indexRow(session, r); 1916 1917 if (session != null) { 1918 session.addInsertAction(this, r); 1919 } 1920 } 1921 1922 1925 void insertNoCheckRollback(Session session, Row row, 1926 boolean log) throws HsqlException { 1927 1928 Row newrow = restoreRow(row); 1929 1930 indexRow(session, newrow); 1933 1934 if (log && isLogged) { 1935 database.logger.writeInsertStatement(session, this, 1936 row.getData()); 1937 } 1938 } 1939 1940 1944 int insertSys(Result ins) throws HsqlException { 1945 1946 Record ni = ins.rRoot; 1947 int count = 0; 1948 1949 while (ni != null) { 1950 insertData(null, ni.data); 1951 1952 ni = ni.next; 1953 1954 count++; 1955 } 1956 1957 return count; 1958 } 1959 1960 1964 int insertResult(Session session, Result ins) throws HsqlException { 1965 1966 Record ni = ins.rRoot; 1967 int count = 0; 1968 1969 while (ni != null) { 1970 Object [] newData = 1971 (Object []) ArrayUtil.resizeArrayIfDifferent(ni.data, 1972 columnCount); 1973 1974 insertData(session, newData); 1975 1976 ni = ni.next; 1977 1978 count++; 1979 } 1980 1981 return count; 1982 } 1983 1984 1989 public void insertFromScript(Object [] data) throws HsqlException { 1990 updateIdentityValue(data); 1991 insertData(null, data); 1992 } 1993 1994 1997 public void insertData(Session session, 1998 Object [] data) throws HsqlException { 1999 2000 Row row = newRow(data); 2001 2002 indexRow(session, row); 2003 commitRowToStore(row); 2004 } 2005 2006 2009 public void insertSys(Object [] data) throws HsqlException { 2010 2011 Row row = newRow(data); 2012 2013 indexRow(null, row); 2014 } 2015 2016 2020 protected void insertFromTextSource(CachedRow row) throws HsqlException { 2021 2022 Object [] data = row.getData(); 2023 2024 updateIdentityValue(data); 2025 enforceFieldValueLimits(data, defaultColumnMap); 2026 enforceNullConstraints(data); 2027 2028 int i = 0; 2029 2030 try { 2031 for (; i < indexList.length; i++) { 2032 indexList[i].insert(null, row, i); 2033 } 2034 } catch (HsqlException e) { 2035 2036 for (--i; i >= 0; i--) { 2038 Node n = row.getNode(i); 2039 2040 indexList[i].delete(null, n); 2041 } 2042 2043 row.delete(); 2044 removeRowFromStore(row); 2045 2046 throw e; 2047 } 2048 } 2049 2050 2053 protected void enforceNullConstraints(Object [] data) 2054 throws HsqlException { 2055 2056 for (int i = 0; i < columnCount; i++) { 2057 if (data[i] == null &&!colNullable[i]) { 2058 Trace.throwerror(Trace.TRY_TO_INSERT_NULL, 2059 "column: " + getColumn(i).columnName.name 2060 + " table: " + tableName.name); 2061 } 2062 } 2063 } 2064 2065 2069 protected void setIdentityColumn(Session session, 2070 Object [] data) throws HsqlException { 2071 2072 if (identityColumn != -1) { 2073 Number id = (Number ) data[identityColumn]; 2074 2075 if (id == null) { 2076 if (colTypes[identityColumn] == Types.INTEGER) { 2077 id = ValuePool.getInt((int) identitySequence.getValue()); 2078 } else { 2079 id = ValuePool.getLong(identitySequence.getValue()); 2080 } 2081 2082 data[identityColumn] = id; 2083 } else { 2084 identitySequence.getValue(id.longValue()); 2085 } 2086 2087 if (session != null) { 2088 session.setLastIdentity(id); 2089 } 2090 } 2091 } 2092 2093 2097 protected void updateIdentityValue(Object [] data) throws HsqlException { 2098 2099 if (identityColumn != -1) { 2100 Number id = (Number ) data[identityColumn]; 2101 2102 if (id != null) { 2103 identitySequence.getValue(id.longValue()); 2104 } 2105 } 2106 } 2107 2108 2112 void enforceFieldValueLimits(Object [] data, 2113 int[] cols) throws HsqlException { 2114 2115 int i; 2116 int colindex; 2117 2118 if (sqlEnforceSize) { 2119 if (cols == null) { 2120 cols = defaultColumnMap; 2121 } 2122 2123 for (i = 0; i < cols.length; i++) { 2124 colindex = cols[i]; 2125 2126 if ((colTypes[colindex] == Types.TIMESTAMP || colSizes[colindex] != 0) 2127 && data[colindex] != null) { 2128 data[colindex] = Column.enforceSize(data[colindex], 2129 colTypes[colindex], 2130 colSizes[colindex], 2131 colScales[colindex], 2132 true); 2133 } 2134 } 2135 } 2136 } 2137 2138 2140 2144 void fireAll(Session session, int trigVecIndx, Object [] oldrow, 2145 Object [] newrow) { 2146 2147 if (!database.isReferentialIntegrity()) { 2148 2149 return; 2151 } 2152 2153 HsqlArrayList trigVec = triggerLists[trigVecIndx]; 2154 2155 if (trigVec == null) { 2156 return; 2157 } 2158 2159 for (int i = 0, size = trigVec.size(); i < size; i++) { 2160 TriggerDef td = (TriggerDef) trigVec.get(i); 2161 2162 td.pushPair(session, oldrow, newrow); } 2164 } 2165 2166 2169 void fireAll(Session session, int trigVecIndex) { 2170 2171 if (triggerLists[trigVecIndex] != null) { 2172 fireAll(session, trigVecIndex, null, null); 2173 } 2174 } 2175 2176 2179 void addTrigger(TriggerDef trigDef) { 2180 2181 if (triggerLists[trigDef.vectorIndex] == null) { 2182 triggerLists[trigDef.vectorIndex] = new HsqlArrayList(); 2183 } 2184 2185 triggerLists[trigDef.vectorIndex].add(trigDef); 2186 } 2187 2188 2191 void dropTrigger(String name) { 2192 2193 int numTrigs = TriggerDef.NUM_TRIGS; 2195 2196 for (int tv = 0; tv < numTrigs; tv++) { 2197 HsqlArrayList v = triggerLists[tv]; 2198 2199 if (v == null) { 2200 continue; 2201 } 2202 2203 for (int tr = v.size() - 1; tr >= 0; tr--) { 2204 TriggerDef td = (TriggerDef) v.get(tr); 2205 2206 if (td.name.name.equals(name)) { 2207 v.remove(tr); 2208 td.terminate(); 2209 } 2210 } 2211 2212 if (v.isEmpty()) { 2213 triggerLists[tv] = null; 2214 } 2215 } 2216 } 2217 2218 2221 void dropTriggers() { 2222 2223 int numTrigs = TriggerDef.NUM_TRIGS; 2225 2226 for (int tv = 0; tv < numTrigs; tv++) { 2227 HsqlArrayList v = triggerLists[tv]; 2228 2229 if (v == null) { 2230 continue; 2231 } 2232 2233 for (int tr = v.size() - 1; tr >= 0; tr--) { 2234 TriggerDef td = (TriggerDef) v.get(tr); 2235 2236 td.terminate(); 2237 } 2238 2239 triggerLists[tv] = null; 2240 } 2241 } 2242 2243 2244 2245 2252 HashSet constraintPath; 2253 2254 2258 HashMappedList tableUpdateList; 2259 2260 2262 2282 static void checkCascadeDelete(Session session, Table table, 2283 HashMappedList tableUpdateLists, Row row, 2284 boolean delete, 2285 HashSet path) throws HsqlException { 2286 2287 for (int i = 0, size = table.constraintList.length; i < size; i++) { 2288 Constraint c = table.constraintList[i]; 2289 2290 if (c.getType() != Constraint.MAIN || c.getRef() == null) { 2291 continue; 2292 } 2293 2294 RowIterator refiterator = c.findFkRef(session, row.getData(), 2295 delete); 2296 2297 if (!refiterator.hasNext()) { 2298 continue; 2299 } 2300 2301 try { 2302 if (c.core.deleteAction == Constraint.NO_ACTION) { 2303 if (c.core.mainTable == c.core.refTable) { 2304 Row refrow = refiterator.next(); 2305 2306 if (row.equals(refrow)) { 2312 continue; 2313 } 2314 } 2315 2316 throw Trace.error(Trace.INTEGRITY_CONSTRAINT_VIOLATION, 2317 Trace.Constraint_violation, 2318 new Object [] { 2319 c.core.fkName.name, c.core.refTable.getName().name 2320 }); 2321 } 2322 2323 Table reftable = c.getRef(); 2324 2325 boolean hasref = 2327 reftable.getNextConstraintIndex(0, Constraint.MAIN) != -1; 2328 2329 if (delete == false && hasref == false) { 2331 continue; 2332 } 2333 2334 Index refindex = c.getRefIndex(); 2335 int[] m_columns = c.getMainColumns(); 2336 int[] r_columns = c.getRefColumns(); 2337 Object [] mdata = row.getData(); 2338 boolean isUpdate = c.getDeleteAction() == Constraint.SET_NULL 2339 || c.getDeleteAction() 2340 == Constraint.SET_DEFAULT; 2341 2342 HashMappedList rowSet = null; 2345 2346 if (isUpdate) { 2347 rowSet = (HashMappedList) tableUpdateLists.get(reftable); 2348 2349 if (rowSet == null) { 2350 rowSet = new HashMappedList(); 2351 2352 tableUpdateLists.add(reftable, rowSet); 2353 } 2354 } 2355 2356 for (;;) { 2358 Row refrow = refiterator.next(); 2359 2360 if (refrow == null || refrow.isCascadeDeleted() 2361 || refindex.compareRowNonUnique( 2362 session, mdata, m_columns, 2363 refrow.getData()) != 0) { 2364 break; 2365 } 2366 2367 if (isUpdate) { 2371 Object [] rnd = reftable.getEmptyRowData(); 2372 2373 System.arraycopy(refrow.getData(), 0, rnd, 0, 2374 rnd.length); 2375 2376 if (c.getDeleteAction() == Constraint.SET_NULL) { 2377 for (int j = 0; j < r_columns.length; j++) { 2378 rnd[r_columns[j]] = null; 2379 } 2380 } else { 2381 for (int j = 0; j < r_columns.length; j++) { 2382 Column col = reftable.getColumn(r_columns[j]); 2383 2384 rnd[r_columns[j]] = 2385 col.getDefaultValue(session); 2386 } 2387 } 2388 2389 if (hasref && path.add(c)) { 2390 2391 checkCascadeUpdate(session, reftable, null, 2395 refrow, rnd, r_columns, null, 2396 path); 2397 path.remove(c); 2398 } 2399 2400 if (delete) { 2401 2402 if (reftable != table ||!refrow.equals(row)) { 2404 mergeUpdate(rowSet, refrow, rnd, r_columns); 2405 } 2406 } 2407 } else if (hasref) { 2408 if (reftable != table) { 2409 if (path.add(c)) { 2410 checkCascadeDelete(session, reftable, 2411 tableUpdateLists, refrow, 2412 delete, path); 2413 path.remove(c); 2414 } 2415 } else { 2416 2417 if (refrow != row) { 2420 checkCascadeDelete(session, reftable, 2421 tableUpdateLists, refrow, 2422 delete, path); 2423 } 2424 } 2425 } 2426 2427 if (delete &&!isUpdate &&!refrow.isCascadeDeleted()) { 2428 reftable.deleteNoRefCheck(session, refrow); 2429 } 2430 } 2431 } finally { 2432 refiterator.release(); 2433 } 2434 } 2435 } 2436 2437 2464 static void checkCascadeUpdate(Session session, Table table, 2465 HashMappedList tableUpdateLists, Row orow, 2466 Object [] nrow, int[] cols, Table ref, 2467 HashSet path) throws HsqlException { 2468 2469 for (int i = 0, size = table.constraintList.length; i < size; i++) { 2472 Constraint c = table.constraintList[i]; 2473 2474 if (c.getType() == Constraint.FOREIGN_KEY && c.getRef() != null) { 2475 2476 if (ref == null || c.getMain() != ref) { 2484 2485 if (ArrayUtil.countCommonElements(cols, c.getRefColumns()) 2487 == 0) { 2488 2489 continue; 2491 } 2492 2493 c.hasMainRef(session, nrow); 2494 } 2495 } else if (c.getType() == Constraint.MAIN && c.getRef() != null) { 2496 2497 int[] common = ArrayUtil.commonElements(cols, 2505 c.getMainColumns()); 2506 2507 if (common == null) { 2508 2509 continue; 2511 } 2512 2513 int[] m_columns = c.getMainColumns(); 2514 int[] r_columns = c.getRefColumns(); 2515 2516 boolean nochange = true; 2518 2519 for (int j = 0; j < m_columns.length; j++) { 2520 if (!orow.getData()[m_columns[j]].equals( 2521 nrow[m_columns[j]])) { 2522 nochange = false; 2523 2524 break; 2525 } 2526 } 2527 2528 if (nochange) { 2529 continue; 2530 } 2531 2532 RowIterator refiterator = c.findFkRef(session, 2535 orow.getData(), false); 2536 2537 if (refiterator.hasNext()) { 2538 if (c.core.updateAction == Constraint.NO_ACTION) { 2539 throw Trace.error( 2540 Trace.INTEGRITY_CONSTRAINT_VIOLATION, 2541 Trace.Constraint_violation, new Object [] { 2542 c.core.fkName.name, c.core.refTable.getName().name 2543 }); 2544 } 2545 } else { 2546 2547 continue; 2549 } 2550 2551 Table reftable = c.getRef(); 2552 2553 boolean hasref = 2555 reftable.getNextConstraintIndex(0, Constraint.MAIN) != -1; 2556 Index refindex = c.getRefIndex(); 2557 2558 HashMappedList rowSet = 2560 (HashMappedList) tableUpdateLists.get(reftable); 2561 2562 if (rowSet == null) { 2563 rowSet = new HashMappedList(); 2564 2565 tableUpdateLists.add(reftable, rowSet); 2566 } 2567 2568 for (Row refrow = refiterator.next(); ; 2569 refrow = refiterator.next()) { 2570 if (refrow == null 2571 || refindex.compareRowNonUnique( 2572 session, orow.getData(), m_columns, 2573 refrow.getData()) != 0) { 2574 break; 2575 } 2576 2577 Object [] rnd = reftable.getEmptyRowData(); 2578 2579 System.arraycopy(refrow.getData(), 0, rnd, 0, rnd.length); 2580 2581 if (c.getUpdateAction() == Constraint.SET_NULL) { 2585 2586 for (int j = 0; j < r_columns.length; j++) { 2589 rnd[r_columns[j]] = null; 2590 } 2591 } else if (c.getUpdateAction() 2592 == Constraint.SET_DEFAULT) { 2593 2594 for (int j = 0; j < r_columns.length; j++) { 2597 Column col = reftable.getColumn(r_columns[j]); 2598 2599 rnd[r_columns[j]] = col.getDefaultValue(session); 2600 } 2601 2602 if (path.add(c)) { 2603 checkCascadeUpdate(session, reftable, 2604 tableUpdateLists, refrow, rnd, 2605 r_columns, null, path); 2606 path.remove(c); 2607 } 2608 } else { 2609 2610 for (int j = 0; j < m_columns.length; j++) { 2613 rnd[r_columns[j]] = nrow[m_columns[j]]; 2614 } 2615 2616 if (path.add(c)) { 2617 checkCascadeUpdate(session, reftable, 2618 tableUpdateLists, refrow, rnd, 2619 common, table, path); 2620 path.remove(c); 2621 } 2622 } 2623 2624 mergeUpdate(rowSet, refrow, rnd, r_columns); 2625 } 2626 } 2627 } 2628 } 2629 2630 2634 static void mergeUpdate(HashMappedList rowSet, Row row, Object [] newData, 2635 int[] cols) { 2636 2637 Object [] data = (Object []) rowSet.get(row); 2638 2639 if (data != null) { 2640 for (int j = 0; j < cols.length; j++) { 2641 data[cols[j]] = newData[cols[j]]; 2642 } 2643 } else { 2644 rowSet.add(row, newData); 2645 } 2646 } 2647 2648 2652 static boolean mergeKeepUpdate(Session session, HashMappedList rowSet, 2653 int[] cols, int[] colTypes, Row row, 2654 Object [] newData) throws HsqlException { 2655 2656 Object [] data = (Object []) rowSet.get(row); 2657 2658 if (data != null) { 2659 if (Index.compareRows( 2660 session, row 2661 .getData(), newData, cols, colTypes) != 0 && Index 2662 .compareRows( 2663 session, newData, data, cols, colTypes) != 0) { 2664 return false; 2665 } 2666 2667 for (int j = 0; j < cols.length; j++) { 2668 newData[cols[j]] = data[cols[j]]; 2669 } 2670 2671 rowSet.put(row, newData); 2672 } else { 2673 rowSet.add(row, newData); 2674 } 2675 2676 return true; 2677 } 2678 2679 static void clearUpdateLists(HashMappedList tableUpdateList) { 2680 2681 for (int i = 0; i < tableUpdateList.size(); i++) { 2682 HashMappedList updateList = 2683 (HashMappedList) tableUpdateList.get(i); 2684 2685 updateList.clear(); 2686 } 2687 } 2688 2689 2693 int delete(Session session, 2694 HsqlArrayList deleteList) throws HsqlException { 2695 2696 HashSet path = constraintPath == null ? new HashSet() 2697 : constraintPath; 2698 2699 constraintPath = null; 2700 2701 HashMappedList tUpdateList = tableUpdateList == null 2702 ? new HashMappedList() 2703 : tableUpdateList; 2704 2705 tableUpdateList = null; 2706 2707 if (database.isReferentialIntegrity()) { 2708 for (int i = 0; i < deleteList.size(); i++) { 2709 Row row = (Row) deleteList.get(i); 2710 2711 path.clear(); 2712 checkCascadeDelete(session, this, tUpdateList, row, false, 2713 path); 2714 } 2715 } 2716 2717 database.txManager.checkDelete(session, deleteList); 2719 2720 for (int i = 0; i < tUpdateList.size(); i++) { 2721 Table table = (Table) tUpdateList.getKey(i); 2722 HashMappedList updateList = (HashMappedList) tUpdateList.get(i); 2723 2724 database.txManager.checkDelete(session, updateList); 2725 } 2726 2727 fireAll(session, Trigger.DELETE_BEFORE); 2729 2730 if (database.isReferentialIntegrity()) { 2731 for (int i = 0; i < deleteList.size(); i++) { 2732 Row row = (Row) deleteList.get(i); 2733 2734 path.clear(); 2735 checkCascadeDelete(session, this, tUpdateList, row, true, 2736 path); 2737 } 2738 } 2739 2740 for (int i = 0; i < deleteList.size(); i++) { 2741 Row row = (Row) deleteList.get(i); 2742 2743 if (!row.isCascadeDeleted()) { 2744 deleteNoRefCheck(session, row); 2745 } 2746 } 2747 2748 for (int i = 0; i < tUpdateList.size(); i++) { 2749 Table table = (Table) tUpdateList.getKey(i); 2750 HashMappedList updateList = (HashMappedList) tUpdateList.get(i); 2751 2752 table.updateRowSet(session, updateList, null, false); 2753 updateList.clear(); 2754 } 2755 2756 fireAll(session, Trigger.DELETE_AFTER); 2757 path.clear(); 2758 2759 constraintPath = path; 2760 tableUpdateList = tUpdateList; 2761 2762 return deleteList.size(); 2763 } 2764 2765 2769 private void deleteNoRefCheck(Session session, 2770 Row row) throws HsqlException { 2771 2772 Object [] data = row.getData(); 2773 2774 fireAll(session, Trigger.DELETE_BEFORE_ROW, data, null); 2775 deleteNoCheck(session, row, true); 2776 2777 fireAll(session, Trigger.DELETE_AFTER_ROW, data, null); 2779 } 2780 2781 2785 private void deleteNoCheck(Session session, Row row, 2786 boolean log) throws HsqlException { 2787 2788 if (row.isCascadeDeleted()) { 2789 return; 2790 } 2791 2792 Object [] data = row.getData(); 2793 2794 row = row.getUpdatedRow(); 2795 2796 for (int i = indexList.length - 1; i >= 0; i--) { 2797 Node node = row.getNode(i); 2798 2799 indexList[i].delete(session, node); 2800 } 2801 2802 row.delete(); 2803 2804 if (session != null) { 2805 session.addDeleteAction(this, row); 2806 } 2807 2808 if (log && isLogged) { 2809 database.logger.writeDeleteStatement(session, this, data); 2810 } 2811 } 2812 2813 2816 public void deleteNoCheckFromLog(Session session, 2817 Object [] data) throws HsqlException { 2818 2819 Row row = null; 2820 2821 if (hasPrimaryKey()) { 2822 RowIterator it = getPrimaryIndex().findFirstRow(session, data, 2823 primaryKeyColsSequence); 2824 2825 row = it.next(); 2826 } else if (bestIndex == null) { 2827 RowIterator it = getPrimaryIndex().firstRow(session); 2828 2829 while (true) { 2830 row = it.next(); 2831 2832 if (row == null) { 2833 break; 2834 } 2835 2836 if (Index.compareRows( 2837 session, row.getData(), data, defaultColumnMap, 2838 colTypes) == 0) { 2839 break; 2840 } 2841 } 2842 } else { 2843 RowIterator it = bestIndex.findFirstRow(session, data); 2844 2845 while (true) { 2846 row = it.next(); 2847 2848 if (row == null) { 2849 break; 2850 } 2851 2852 Object [] rowdata = row.getData(); 2853 2854 if (bestIndex.compareRowNonUnique( 2856 session, data, bestIndex.getColumns(), 2857 rowdata) != 0) { 2858 row = null; 2859 2860 break; 2861 } 2862 2863 if (Index.compareRows( 2864 session, rowdata, data, defaultColumnMap, 2865 colTypes) == 0) { 2866 break; 2867 } 2868 } 2869 } 2870 2871 if (row == null) { 2872 return; 2873 } 2874 2875 database.txManager.checkDelete(session, row); 2877 2878 for (int i = indexList.length - 1; i >= 0; i--) { 2879 Node node = row.getNode(i); 2880 2881 indexList[i].delete(session, node); 2882 } 2883 2884 row.delete(); 2885 2886 if (session != null) { 2887 session.addDeleteAction(this, row); 2888 } 2889 } 2890 2891 2895 void deleteNoCheckRollback(Session session, Row row, 2896 boolean log) throws HsqlException { 2897 2898 row = indexList[0].findRow(session, row); 2899 2900 for (int i = indexList.length - 1; i >= 0; i--) { 2901 Node node = row.getNode(i); 2902 2903 indexList[i].delete(session, node); 2904 } 2905 2906 row.delete(); 2907 removeRowFromStore(row); 2908 2909 if (log && isLogged) { 2910 database.logger.writeDeleteStatement(session, this, 2911 row.getData()); 2912 } 2913 } 2914 2915 2940 int update(Session session, HashMappedList updateList, 2941 int[] cols) throws HsqlException { 2942 2943 HashSet path = constraintPath == null ? new HashSet() 2944 : constraintPath; 2945 2946 constraintPath = null; 2947 2948 HashMappedList tUpdateList = tableUpdateList == null 2949 ? new HashMappedList() 2950 : tableUpdateList; 2951 2952 tableUpdateList = null; 2953 2954 for (int i = 0; i < updateList.size(); i++) { 2956 Object [] data = (Object []) updateList.get(i); 2957 2958 setIdentityColumn(session, data); 2961 enforceFieldValueLimits(data, cols); 2962 enforceNullConstraints(data); 2963 } 2964 2965 if (database.isReferentialIntegrity()) { 2967 for (int i = 0; i < updateList.size(); i++) { 2968 Object [] data = (Object []) updateList.get(i); 2969 Row row = (Row) updateList.getKey(i); 2970 2971 checkCascadeUpdate(session, this, tUpdateList, row, data, 2972 cols, null, path); 2973 } 2974 } 2975 2976 fireAll(session, Trigger.UPDATE_BEFORE); 2977 2978 HashMappedList triggeredList = (HashMappedList) tUpdateList.get(this); 2980 2981 if (triggeredList != null) { 2982 for (int i = 0; i < triggeredList.size(); i++) { 2983 Row row = (Row) triggeredList.getKey(i); 2984 Object [] data = (Object []) triggeredList.get(i); 2985 2986 mergeKeepUpdate(session, updateList, cols, colTypes, row, 2987 data); 2988 } 2989 2990 triggeredList.clear(); 2991 } 2992 2993 for (int i = 0; i < tUpdateList.size(); i++) { 2995 Table table = (Table) tUpdateList.getKey(i); 2996 HashMappedList updateListT = (HashMappedList) tUpdateList.get(i); 2997 2998 database.txManager.checkDelete(session, updateListT); 2999 } 3000 3001 database.txManager.checkDelete(session, updateList); 3002 3003 for (int i = 0; i < tUpdateList.size(); i++) { 3005 Table table = (Table) tUpdateList.getKey(i); 3006 HashMappedList updateListT = (HashMappedList) tUpdateList.get(i); 3007 3008 table.updateRowSet(session, updateListT, null, false); 3009 updateListT.clear(); 3010 } 3011 3012 updateRowSet(session, updateList, cols, true); 3013 fireAll(session, Trigger.UPDATE_AFTER); 3014 path.clear(); 3015 3016 constraintPath = path; 3017 tableUpdateList = tUpdateList; 3018 3019 clearUpdateLists(tableUpdateList); 3020 3021 return updateList.size(); 3022 } 3023 3024 void updateRowSet(Session session, HashMappedList rowSet, int[] cols, 3025 boolean nodelete) throws HsqlException { 3026 3027 for (int i = rowSet.size() - 1; i >= 0; i--) { 3028 Row row = (Row) rowSet.getKey(i); 3029 Object [] data = (Object []) rowSet.get(i); 3030 3031 if (row.isCascadeDeleted()) { 3032 if (nodelete) { 3033 throw Trace.error(Trace.TRIGGERED_DATA_CHANGE); 3034 } else { 3035 rowSet.remove(i); 3036 3037 continue; 3038 } 3039 } 3040 3041 for (int j = 0; j < constraintList.length; j++) { 3042 Constraint c = constraintList[j]; 3043 3044 if (c.getType() == Constraint.CHECK) { 3045 c.checkCheckConstraint(session, data); 3046 3047 continue; 3048 } 3049 } 3050 3051 deleteNoCheck(session, row, true); 3052 } 3053 3054 for (int i = 0; i < rowSet.size(); i++) { 3055 Row row = (Row) rowSet.getKey(i); 3056 Object [] data = (Object []) rowSet.get(i); 3057 3058 if (triggerLists[Trigger.UPDATE_BEFORE_ROW] != null) { 3059 fireAll(session, Trigger.UPDATE_BEFORE_ROW, row.getData(), 3060 data); 3061 checkRowDataUpdate(session, data, cols); 3062 } 3063 3064 insertNoCheck(session, data); 3065 3066 if (triggerLists[Trigger.UPDATE_AFTER_ROW] != null) { 3067 fireAll(session, Trigger.UPDATE_AFTER_ROW, row.getData(), 3068 data); 3069 checkRowDataUpdate(session, data, cols); 3070 } 3071 } 3072 } 3073 3074 void checkRowDataInsert(Session session, 3075 Object [] data) throws HsqlException { 3076 3077 enforceFieldValueLimits(data, null); 3078 enforceNullConstraints(data); 3079 3080 if (database.isReferentialIntegrity()) { 3081 for (int i = 0, size = constraintList.length; i < size; i++) { 3082 constraintList[i].checkInsert(session, data); 3083 } 3084 } 3085 } 3086 3087 void checkRowDataUpdate(Session session, Object [] data, 3088 int[] cols) throws HsqlException { 3089 3090 enforceFieldValueLimits(data, cols); 3091 enforceNullConstraints(data); 3092 3093 for (int j = 0; j < constraintList.length; j++) { 3094 Constraint c = constraintList[j]; 3095 3096 if (c.getType() == Constraint.CHECK) { 3097 c.checkCheckConstraint(session, data); 3098 } 3099 } 3100 } 3101 3102 3107 public boolean isCached() { 3108 return isCached; 3109 } 3110 3111 3114 boolean isIndexCached() { 3115 return isCached; 3116 } 3117 3118 3121 int getIndexIndex(String indexName) { 3122 3123 Index[] indexes = indexList; 3124 3125 for (int i = 0; i < indexes.length; i++) { 3126 if (indexName.equals(indexes[i].getName().name)) { 3127 return i; 3128 } 3129 } 3130 3131 return -1; 3133 } 3134 3135 3138 Index getIndex(String indexName) { 3139 3140 Index[] indexes = indexList; 3141 int i = getIndexIndex(indexName); 3142 3143 return i == -1 ? null 3144 : indexes[i]; 3145 } 3146 3147 3150 int getConstraintIndex(String constraintName) { 3151 3152 for (int i = 0, size = constraintList.length; i < size; i++) { 3153 if (constraintList[i].getName().name.equals(constraintName)) { 3154 return i; 3155 } 3156 } 3157 3158 return -1; 3159 } 3160 3161 3164 Constraint getConstraint(String constraintName) { 3165 3166 int i = getConstraintIndex(constraintName); 3167 3168 return (i < 0) ? null 3169 : (Constraint) constraintList[i]; 3170 } 3171 3172 3175 void removeConstraint(String name) { 3176 3177 int index = getConstraintIndex(name); 3178 3179 constraintList = 3180 (Constraint[]) ArrayUtil.toAdjustedArray(constraintList, null, 3181 index, -1); 3182 } 3183 3184 3187 Column getColumn(int i) { 3188 return (Column) columnList.get(i); 3189 } 3190 3191 void renameColumn(Column column, String newName, 3192 boolean isquoted) throws HsqlException { 3193 3194 String oldname = column.columnName.name; 3195 int i = getColumnNr(oldname); 3196 3197 columnList.setKey(i, newName); 3198 column.columnName.rename(newName, isquoted); 3199 renameColumnInCheckConstraints(oldname, newName, isquoted); 3200 } 3201 3202 3205 public int[] getColumnTypes() { 3206 return colTypes; 3207 } 3208 3209 3212 public Index getIndex(int i) { 3213 return indexList[i]; 3214 } 3215 3216 public Index[] getIndexes() { 3217 return indexList; 3218 } 3219 3220 3227 CachedRow getRow(int pos, Node primarynode) throws HsqlException { 3228 3229 if (isText) { 3230 CachedDataRow row = (CachedDataRow) rowStore.get(pos); 3231 3232 row.nPrimaryNode = primarynode; 3233 3234 return row; 3235 } else if (isCached) { 3236 return (CachedRow) rowStore.get(pos); 3237 } 3238 3239 return null; 3240 } 3241 3242 3245 CachedRow getRow(int pos) { 3246 return (CachedRow) rowStore.get(pos); 3247 } 3248 3249 3252 CachedRow getRow(long id) { 3253 return (CachedRow) rowStore.get((int) id); 3254 } 3255 3256 3259 void removeRowFromStore(Row row) throws HsqlException { 3260 3261 if (isCached || isText && cache != null) { 3262 rowStore.remove(row.getPos()); 3263 } 3264 } 3265 3266 void releaseRowFromStore(Row row) throws HsqlException { 3267 3268 if (isCached || isText && cache != null) { 3269 rowStore.release(row.getPos()); 3270 } 3271 } 3272 3273 void commitRowToStore(Row row) { 3274 3275 if (isText && cache != null) { 3276 rowStore.commit(row); 3277 } 3278 } 3279 3280 void indexRow(Session session, Row row) throws HsqlException { 3281 3282 int i = 0; 3283 3284 try { 3285 for (; i < indexList.length; i++) { 3286 indexList[i].insert(session, row, i); 3287 } 3288 } catch (HsqlException e) { 3289 Index index = indexList[i]; 3290 boolean isconstraint = index.isConstraint; 3291 3292 for (--i; i >= 0; i--) { 3294 Node n = row.getNode(i); 3295 3296 indexList[i].delete(session, n); 3297 } 3298 3299 row.delete(); 3300 removeRowFromStore(row); 3301 3302 if (isconstraint) { 3303 Constraint c = getUniqueOrPKConstraintForIndex(index); 3304 String name = c == null ? index.getName().name 3305 : c.getName().name; 3306 3307 throw Trace.error(Trace.VIOLATION_OF_UNIQUE_CONSTRAINT, name); 3308 } 3309 3310 throw e; 3311 } 3312 } 3313 3314 3317 void clearAllRows(Session session) { 3318 3319 for (int i = 0; i < indexList.length; i++) { 3320 indexList[i].clearAll(session); 3321 } 3322 3323 if (!isTemp) { 3324 identitySequence.reset(); 3325 rowIdSequence.reset(); 3326 } 3327 } 3328 3329 3330 void drop() throws HsqlException {} 3331 3332 boolean isWritable() { 3333 return !isReadOnly &&!database.databaseReadOnly 3334 &&!(database.isFilesReadOnly() && (isCached || isText)); 3335 } 3336 3337 3340 String getCatalogName() { 3341 3342 return database.getProperties().isPropertyTrue("hsqldb.catalogs") 3344 ? database.getURI() 3345 : null; 3346 } 3347 3348 3351 public String getSchemaName() { 3352 return tableName.schema.name; 3353 } 3354 3355 public int getRowCount(Session session) throws HsqlException { 3356 return getPrimaryIndex().size(session); 3357 } 3358 3359 3363 public void resetRowId(Session session) throws HsqlException { 3364 3365 if (isCached) { 3366 return; 3367 } 3368 3369 rowIdSequence = new NumberSequence(null, 0, 1, Types.BIGINT); 3370 3371 RowIterator it = getPrimaryIndex().firstRow(session);; 3372 3373 while (it.hasNext()) { 3374 Row row = it.next(); 3375 int pos = (int) rowIdSequence.getValue(); 3376 3377 row.setPos(pos); 3378 } 3379 } 3380 3381 3384 Row newRow(Object [] o) throws HsqlException { 3385 3386 Row row; 3387 3388 try { 3389 if (isMemory) { 3390 row = new Row(this, o); 3391 3392 int pos = (int) rowIdSequence.getValue(); 3393 3394 row.setPos(pos); 3395 } else { 3396 row = CachedRow.newCachedRow(this, o); 3397 3398 rowStore.add(row); 3399 } 3400 } catch (IOException e) { 3401 throw new HsqlException( 3402 e, Trace.getMessage(Trace.GENERAL_IO_ERROR), 3403 Trace.GENERAL_IO_ERROR); 3404 } 3405 3406 return row; 3407 } 3408 3409 Row restoreRow(Row oldrow) throws HsqlException { 3410 3411 Row row; 3412 3413 try { 3414 if (isMemory) { 3415 row = new Row(this, oldrow.oData); 3416 3417 row.setPos(oldrow.getPos()); 3418 } else { 3419 row = CachedRow.newCachedRow(this, oldrow.oData); 3420 3421 row.setStorageSize(oldrow.getStorageSize()); 3422 row.setPos(oldrow.getPos()); 3423 rowStore.restore(row); 3424 } 3425 } catch (IOException e) { 3426 throw new HsqlException( 3427 e, Trace.getMessage(Trace.GENERAL_IO_ERROR), 3428 Trace.GENERAL_IO_ERROR); 3429 } 3430 3431 return row; 3432 } 3433 3434 public class RowStore implements PersistentStore { 3435 3436 public CachedObject get(int i) { 3437 3438 try { 3439 return cache.get(i, this, false); 3440 } catch (HsqlException e) { 3441 return null; 3442 } 3443 } 3444 3445 public CachedObject getKeep(int i) { 3446 3447 try { 3448 return cache.get(i, this, true); 3449 } catch (HsqlException e) { 3450 return null; 3451 } 3452 } 3453 3454 public int getStorageSize(int i) { 3455 3456 try { 3457 return cache.get(i, this, false).getStorageSize(); 3458 } catch (HsqlException e) { 3459 return 0; 3460 } 3461 } 3462 3463 public void add(CachedObject row) throws IOException { 3464 cache.add(row); 3465 } 3466 3467 public void restore(CachedObject row) throws IOException { 3468 cache.restore(row); 3469 } 3470 3471 public CachedObject get(RowInputInterface in) { 3472 3473 try { 3474 if (Table.this.isText) { 3475 return new CachedDataRow(Table.this, in); 3476 } 3477 3478 CachedObject row = new CachedRow(Table.this, in); 3479 3480 return row; 3481 } catch (HsqlException e) { 3482 return null; 3483 } catch (IOException e) { 3484 return null; 3485 } 3486 } 3487 3488 public CachedObject getNewInstance(int size) { 3489 return null; 3490 } 3491 3492 public void remove(int i) { 3493 3494 try { 3495 cache.remove(i, this); 3496 } catch (IOException e) {} 3497 } 3498 3499 public void removePersistence(int i) { 3500 3501 try { 3502 cache.removePersistence(i, this); 3503 } catch (IOException e) { 3504 3505 } 3507 } 3508 3509 public void release(int i) { 3510 cache.release(i); 3511 } 3512 3513 public void commit(CachedObject row) { 3514 3515 try { 3516 if (Table.this.isText) { 3517 cache.saveRow(row); 3518 } 3519 } catch (IOException e) { 3520 3521 } 3523 } 3524 } 3525} 3526 | Popular Tags |