1 21 22 package org.apache.derby.impl.sql.execute; 23 24 import org.apache.derby.iapi.services.monitor.Monitor; 25 import org.apache.derby.iapi.services.sanity.SanityManager; 26 import org.apache.derby.iapi.error.StandardException; 27 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 28 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator; 29 import org.apache.derby.iapi.sql.ResultDescription; 30 import org.apache.derby.iapi.sql.execute.CursorResultSet; 31 import org.apache.derby.iapi.sql.execute.ExecRow; 32 import org.apache.derby.iapi.sql.execute.ExecIndexRow; 33 import org.apache.derby.iapi.sql.execute.ExecutionContext; 34 import org.apache.derby.iapi.sql.execute.ExecutionFactory; 35 36 import org.apache.derby.iapi.reference.SQLState; 37 38 import org.apache.derby.iapi.sql.Activation; 39 40 import org.apache.derby.iapi.store.access.ConglomerateController; 41 import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo; 42 import org.apache.derby.iapi.store.access.ScanController; 43 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo; 44 import org.apache.derby.iapi.store.access.TransactionController; 45 46 import org.apache.derby.catalog.UUID; 47 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 48 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 49 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 50 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor; 51 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList; 52 53 import org.apache.derby.iapi.types.DataValueDescriptor; 54 import org.apache.derby.iapi.types.RowLocation; 55 56 import org.apache.derby.iapi.services.io.FormatableBitSet; 57 import org.apache.derby.iapi.services.i18n.MessageService; 58 import java.util.Properties ; 59 60 63 public class IndexChanger 64 { 65 private IndexRowGenerator irg; 66 private long indexCID; 68 private DynamicCompiledOpenConglomInfo indexDCOCI; 69 private StaticCompiledOpenConglomInfo indexSCOCI; 70 private String indexName; 71 private ConglomerateController baseCC; 72 private TransactionController tc; 73 private int lockMode; 74 private FormatableBitSet baseRowReadMap; 75 76 private ConglomerateController indexCC = null; 77 private ScanController indexSC = null; 78 79 private LanguageConnectionContext lcc; 80 81 private ExecIndexRow ourIndexRow = null; 84 private ExecIndexRow ourUpdatedIndexRow = null; 85 86 private TemporaryRowHolderImpl rowHolder = null; 87 private boolean rowHolderPassedIn; 88 private int isolationLevel; 89 private Activation activation; 90 private boolean ownIndexSC = true; 91 92 108 public IndexChanger 109 ( 110 IndexRowGenerator irg, 111 long indexCID, 112 StaticCompiledOpenConglomInfo indexSCOCI, 113 DynamicCompiledOpenConglomInfo indexDCOCI, 114 String indexName, 115 ConglomerateController baseCC, 116 TransactionController tc, 117 int lockMode, 118 FormatableBitSet baseRowReadMap, 119 int isolationLevel, 120 Activation activation 121 ) 122 throws StandardException 123 { 124 this.irg = irg; 125 this.indexCID = indexCID; 126 this.indexSCOCI = indexSCOCI; 127 this.indexDCOCI = indexDCOCI; 128 this.baseCC = baseCC; 129 this.tc = tc; 130 this.lockMode = lockMode; 131 this.baseRowReadMap = baseRowReadMap; 132 this.rowHolderPassedIn = false; 133 this.isolationLevel = isolationLevel; 134 this.activation = activation; 135 this.indexName = indexName; 136 137 if (activation != null && activation.getIndexConglomerateNumber() == indexCID) 139 { 140 ownIndexSC = false; 141 } 142 143 if (SanityManager.DEBUG) 144 { 145 SanityManager.ASSERT(tc != null, 146 "TransactionController argument to constructor is null"); 147 SanityManager.ASSERT(irg != null, 148 "IndexRowGenerator argument to constructor is null"); 149 } 150 } 151 152 161 public void setRowHolder(TemporaryRowHolderImpl rowHolder) 162 { 163 this.rowHolder = rowHolder; 164 rowHolderPassedIn = (rowHolder != null); 165 } 166 167 173 public void setBaseCC(ConglomerateController baseCC) 174 { 175 this.baseCC = baseCC; 176 } 177 178 186 private void setOurIndexRow(ExecRow baseRow, 187 RowLocation baseRowLoc) 188 throws StandardException 189 { 190 if (ourIndexRow == null) 191 ourIndexRow = irg.getIndexRowTemplate(); 192 193 irg.getIndexRow(baseRow, baseRowLoc, ourIndexRow, baseRowReadMap); 194 } 195 196 204 private void setOurUpdatedIndexRow(ExecRow baseRow, 205 RowLocation baseRowLoc) 206 throws StandardException 207 { 208 if (ourUpdatedIndexRow == null) 209 ourUpdatedIndexRow = irg.getIndexRowTemplate(); 210 211 irg.getIndexRow(baseRow, baseRowLoc, ourUpdatedIndexRow, baseRowReadMap); 212 } 213 214 223 private boolean indexRowChanged() 224 throws StandardException 225 { 226 int numColumns = ourIndexRow.nColumns(); 227 for (int index = 1; index <= numColumns; index++) 228 { 229 DataValueDescriptor oldOrderable = ourIndexRow.getColumn(index); 230 DataValueDescriptor newOrderable = ourUpdatedIndexRow.getColumn(index); 231 if (! (oldOrderable.compare(DataValueDescriptor.ORDER_OP_EQUALS, newOrderable, true, true))) 232 { 233 return true; 234 } 235 } 236 return false; 237 } 238 239 private ExecIndexRow getDeferredIndexRowTemplate(ExecRow baseRow, 240 RowLocation baseRowLoc) 241 throws StandardException 242 { 243 ExecIndexRow template; 244 245 template = irg.getIndexRowTemplate(); 246 247 irg.getIndexRow(baseRow, baseRowLoc, template, baseRowReadMap); 248 249 return template; 250 } 251 252 259 private void setScan() 260 throws StandardException 261 { 262 263 if (! ownIndexSC) 264 { 265 indexSC = activation.getIndexScanController(); 266 } 267 else if (indexSC == null) 268 { 269 RowLocation templateBaseRowLocation = baseCC.newRowLocationTemplate(); 270 271 if (indexSCOCI == null) 272 { 273 indexSC = 274 tc.openScan( 275 indexCID, 276 false, 277 TransactionController.OPENMODE_FORUPDATE, 278 lockMode, 279 isolationLevel, 280 (FormatableBitSet)null, 281 ourIndexRow.getRowArray(), 282 ScanController.GE, 283 null, 284 ourIndexRow.getRowArray(), 285 ScanController.GT 286 ); 287 } 288 else 289 { 290 indexSC = 291 tc.openCompiledScan( 292 false, 293 TransactionController.OPENMODE_FORUPDATE, 294 lockMode, 295 isolationLevel, 296 (FormatableBitSet)null, 297 ourIndexRow.getRowArray(), 298 ScanController.GE, 299 null, 300 ourIndexRow.getRowArray(), 301 ScanController.GT, 302 indexSCOCI, 303 indexDCOCI 304 ); 305 } 306 } 307 else 308 { 309 indexSC.reopenScan( 310 ourIndexRow.getRowArray(), 311 ScanController.GE, 312 null, 313 ourIndexRow.getRowArray(), 314 ScanController.GT 315 ); 316 } 317 } 318 319 322 private void closeIndexCC() 323 throws StandardException 324 { 325 if (indexCC != null) 326 indexCC.close(); 327 indexCC = null; 328 } 329 330 333 private void closeIndexSC() 334 throws StandardException 335 { 336 337 if (ownIndexSC && indexSC != null) 338 { 339 indexSC.close(); 340 indexSC = null; 341 } 342 } 343 344 353 private void doDelete() 354 throws StandardException 355 { 356 if (ownIndexSC) 357 { 358 if (! indexSC.next()) 359 { 360 373 if (SanityManager.DEBUG) 374 SanityManager.THROWASSERT( 375 "Index row "+RowUtil.toString(ourIndexRow)+ 376 " not found in conglomerateid " + indexCID + 377 "Current scan = " + indexSC); 378 379 Object [] args = new Object [2]; 380 args[0] = ourIndexRow.getRowArray()[ourIndexRow.getRowArray().length - 1]; 381 args[1] = new Long (indexCID); 382 383 Monitor.getStream().println(MessageService.getCompleteMessage( 384 SQLState.LANG_IGNORE_MISSING_INDEX_ROW_DURING_DELETE, 385 args)); 386 387 return; 389 } 390 } 391 392 indexSC.delete(); 393 } 394 395 403 private void doInsert() 404 throws StandardException 405 { 406 insertAndCheckDups(ourIndexRow); 407 } 408 409 417 private void doDeferredInsert() 418 throws StandardException 419 { 420 if (rowHolder == null) 421 { 422 Properties properties = new Properties (); 423 424 openIndexCC().getInternalTablePropertySet(properties); 426 427 434 rowHolder = new TemporaryRowHolderImpl(activation, properties, 435 (ResultDescription) null); 436 } 437 438 444 if (!rowHolderPassedIn) 445 { 446 rowHolder.insert(ourIndexRow); 447 } 448 } 449 450 458 private void insertAndCheckDups(ExecIndexRow row) 459 throws StandardException 460 { 461 openIndexCC(); 462 463 int insertStatus = indexCC.insert(row.getRowArray()); 464 465 if (insertStatus == ConglomerateController.ROWISDUPLICATE) 466 { 467 470 String indexOrConstraintName = indexName; 471 LanguageConnectionContext lcc = 473 activation.getLanguageConnectionContext(); 474 DataDictionary dd = lcc.getDataDictionary(); 475 ConglomerateDescriptor cd = dd.getConglomerateDescriptor(indexCID); 477 478 UUID tableID = cd.getTableID(); 479 TableDescriptor td = dd.getTableDescriptor(tableID); 480 String tableName = td.getName(); 481 482 if (indexOrConstraintName == null) { 484 ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td, 485 cd.getUUID()); 486 indexOrConstraintName = conDesc.getConstraintName(); 487 } 488 489 StandardException se = 490 StandardException.newException( 491 SQLState.LANG_DUPLICATE_KEY_CONSTRAINT, indexOrConstraintName, tableName); 492 throw se; 493 } 494 if (SanityManager.DEBUG) 495 { 496 if (insertStatus != 0) 497 { 498 SanityManager.THROWASSERT("Unknown insert status " + insertStatus); 499 } 500 } 501 } 502 503 504 511 private ConglomerateController openIndexCC() 512 throws StandardException 513 { 514 if (indexCC == null) 515 { 516 517 if (indexSCOCI == null) 518 { 519 indexCC = 520 tc.openConglomerate( 521 indexCID, 522 false, 523 (TransactionController.OPENMODE_FORUPDATE | 524 TransactionController.OPENMODE_BASEROW_INSERT_LOCKED), 525 lockMode, 526 isolationLevel); 527 } 528 else 529 { 530 indexCC = 531 tc.openCompiledConglomerate( 532 false, 533 (TransactionController.OPENMODE_FORUPDATE | 534 TransactionController.OPENMODE_BASEROW_INSERT_LOCKED), 535 lockMode, 536 isolationLevel, 537 indexSCOCI, 538 indexDCOCI); 539 } 540 } 541 542 return indexCC; 543 } 544 545 550 public void open() 551 throws StandardException 552 { 553 } 554 555 562 public void delete(ExecRow baseRow, 563 RowLocation baseRowLocation) 564 throws StandardException 565 { 566 setOurIndexRow(baseRow, baseRowLocation); 567 setScan(); 568 doDelete(); 569 } 570 571 580 public void update(ExecRow oldBaseRow, 581 ExecRow newBaseRow, 582 RowLocation baseRowLocation 583 ) 584 throws StandardException 585 { 586 setOurIndexRow(oldBaseRow, baseRowLocation); 587 setOurUpdatedIndexRow(newBaseRow, baseRowLocation); 588 589 593 if (indexRowChanged()) 594 { 595 setScan(); 596 doDelete(); 597 insertForUpdate(newBaseRow, baseRowLocation); 598 } 599 } 600 601 609 public void insert(ExecRow newRow, RowLocation baseRowLocation) 610 throws StandardException 611 { 612 setOurIndexRow(newRow, baseRowLocation); 613 doInsert(); 614 } 615 616 629 void insertForUpdate(ExecRow newRow, RowLocation baseRowLocation) 630 throws StandardException 631 { 632 setOurIndexRow(newRow, baseRowLocation); 633 634 if (irg.isUnique()) 635 { 636 doDeferredInsert(); 637 } 638 else 639 { 640 doInsert(); 641 } 642 } 643 644 651 public void finish() 652 throws StandardException 653 { 654 ExecRow deferredRow; 655 ExecIndexRow deferredIndexRow = new IndexRow(); 656 657 658 if (rowHolder != null) 659 { 660 CursorResultSet rs = rowHolder.getResultSet(); 661 try 662 { 663 rs.open(); 664 while ((deferredRow = rs.getNextRow()) != null) 665 { 666 if (SanityManager.DEBUG) 667 { 668 if (!(deferredRow instanceof ExecIndexRow)) 669 { 670 SanityManager.THROWASSERT("deferredRow isn't an instance "+ 671 "of ExecIndexRow as expected. "+ 672 "It is an "+deferredRow.getClass().getName()); 673 } 674 } 675 insertAndCheckDups((ExecIndexRow)deferredRow); 676 } 677 } 678 finally 679 { 680 rs.close(); 681 682 686 if (!rowHolderPassedIn) 687 { 688 rowHolder.close(); 689 } 690 } 691 } 692 } 693 694 699 public void close() 700 throws StandardException 701 { 702 closeIndexCC(); 703 closeIndexSC(); 704 if (rowHolder != null && !rowHolderPassedIn) 705 { 706 rowHolder.close(); 707 } 708 baseCC = null; 709 } 710 } 711 | Popular Tags |