1 21 22 package org.apache.derby.impl.sql.execute; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 26 import org.apache.derby.iapi.services.loader.ClassFactory; 27 import org.apache.derby.iapi.services.loader.ClassInspector; 28 29 import org.apache.derby.iapi.services.stream.HeaderPrintWriter; 30 31 import org.apache.derby.iapi.sql.execute.ConstantAction; 32 import org.apache.derby.iapi.sql.execute.ExecutionContext; 33 import org.apache.derby.iapi.sql.execute.ExecRow; 34 import org.apache.derby.iapi.sql.execute.ExecIndexRow; 35 36 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor; 37 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList; 38 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptorList; 39 import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator; 40 import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext; 41 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 42 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 43 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor; 44 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor; 45 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator; 46 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 47 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor; 48 import org.apache.derby.iapi.sql.dictionary.StatisticsDescriptor; 49 import org.apache.derby.iapi.sql.depend.DependencyManager; 50 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 51 import org.apache.derby.iapi.sql.Activation; 52 53 import org.apache.derby.iapi.types.DataValueFactory; 54 import org.apache.derby.iapi.types.DataTypeDescriptor; 55 import org.apache.derby.iapi.types.TypeId; 56 import org.apache.derby.iapi.types.RowLocation; 57 58 import org.apache.derby.iapi.reference.SQLState; 59 60 import org.apache.derby.iapi.error.StandardException; 61 62 import org.apache.derby.iapi.store.access.ColumnOrdering; 63 import org.apache.derby.iapi.store.access.ConglomerateController; 64 import org.apache.derby.iapi.store.access.GroupFetchScanController; 65 import org.apache.derby.iapi.store.access.RowLocationRetRowSource; 66 import org.apache.derby.iapi.store.access.ScanController; 67 import org.apache.derby.iapi.store.access.SortObserver; 68 import org.apache.derby.iapi.store.access.SortController; 69 import org.apache.derby.iapi.store.access.TransactionController; 70 import org.apache.derby.iapi.types.DataValueDescriptor; 71 72 73 import org.apache.derby.catalog.UUID; 74 import org.apache.derby.catalog.types.StatisticsImpl; 75 76 import java.util.Properties ; 77 import org.apache.derby.iapi.services.io.FormatableBitSet; 78 79 85 86 class CreateIndexConstantAction extends IndexConstantAction 87 { 88 89 private boolean unique; 90 private String indexType; 91 private long conglomId; 92 private String [] columnNames; 93 private boolean[] isAscending; 94 private boolean isConstraint; 95 private UUID conglomerateUUID; 96 private Properties properties; 97 98 private ExecRow indexTemplateRow; 99 100 101 118 CreateIndexConstantAction( 119 boolean unique, 120 String indexType, 121 String schemaName, 122 String indexName, 123 String tableName, 124 UUID tableId, 125 long conglomId, 126 String [] columnNames, 127 boolean[] isAscending, 128 boolean isConstraint, 129 UUID conglomerateUUID, 130 Properties properties) 131 { 132 super(tableId, indexName, tableName, schemaName); 133 this.unique = unique; 134 this.indexType = indexType; 135 this.conglomId= conglomId; 136 this.columnNames = columnNames; 137 this.isAscending = isAscending; 138 this.isConstraint = isConstraint; 139 this.conglomerateUUID = conglomerateUUID; 140 this.properties = properties; 141 } 142 143 149 public String toString() 150 { 151 return "CREATE INDEX " + indexName; 154 } 155 156 158 159 166 public void executeConstantAction( Activation activation ) 167 throws StandardException 168 { 169 boolean forCreateTable; 170 TableDescriptor td; 171 UUID toid; 172 ColumnDescriptor columnDescriptor; 173 int[] baseColumnPositions; 174 IndexRowGenerator indexRowGenerator = null; 175 ExecRow[] baseRows; 176 ExecIndexRow[] indexRows; 177 ExecRow[] compactBaseRows; 178 GroupFetchScanController scan; 179 RowLocationRetRowSource rowSource; 180 long sortId; 181 int maxBaseColumnPosition = -1; 182 183 LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); 184 DataDictionary dd = lcc.getDataDictionary(); 185 DependencyManager dm = dd.getDependencyManager(); 186 TransactionController tc = lcc.getTransactionExecute(); 187 188 189 forCreateTable = activation.getForCreateTable(); 190 191 200 dd.startWriting(lcc); 201 202 208 SchemaDescriptor sd = dd.getSchemaDescriptor(schemaName, tc, true) ; 209 210 211 212 216 td = activation.getDDLTableDescriptor(); 217 218 if (td == null) 219 { 220 224 if (tableId != null) 225 { 226 td = dd.getTableDescriptor(tableId); 227 } 228 else 229 { 230 td = dd.getTableDescriptor(tableName, sd); 231 } 232 } 233 234 if (td == null) 235 { 236 throw StandardException.newException(SQLState.LANG_CREATE_INDEX_NO_TABLE, 237 indexName, tableName); 238 } 239 240 if (td.getTableType() == TableDescriptor.SYSTEM_TABLE_TYPE) 241 { 242 throw StandardException.newException(SQLState.LANG_CREATE_SYSTEM_INDEX_ATTEMPTED, 243 indexName, tableName); 244 } 245 246 251 lockTableForDDL(tc, td.getHeapConglomerateId(), false); 252 253 if (! forCreateTable) 256 { 257 dm.invalidateFor(td, DependencyManager.CREATE_INDEX, lcc); 258 } 259 260 baseColumnPositions = new int[columnNames.length]; 262 for (int i = 0; i < columnNames.length; i++) 263 { 264 columnDescriptor = td.getColumnDescriptor(columnNames[i]); 266 if (columnDescriptor == null) 267 { 268 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, 269 columnNames[i], 270 tableName); 271 } 272 273 TypeId typeId = columnDescriptor.getType().getTypeId(); 274 275 ClassFactory cf = lcc.getLanguageConnectionFactory().getClassFactory(); 277 boolean isIndexable = typeId.orderable(cf); 278 279 if (isIndexable && typeId.userType()) { 280 String userClass = typeId.getCorrespondingJavaTypeName(); 281 282 try { 287 if (cf.isApplicationClass(cf.loadApplicationClass(userClass))) 288 isIndexable = false; 289 } catch (ClassNotFoundException cnfe) { 290 isIndexable = false; 292 } 293 } 294 295 if (!isIndexable) { 296 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, 297 typeId.getSQLTypeName()); 298 } 299 300 baseColumnPositions[i] = columnDescriptor.getPosition(); 302 303 if (maxBaseColumnPosition < baseColumnPositions[i]) 304 maxBaseColumnPosition = baseColumnPositions[i]; 305 } 306 307 ConglomerateDescriptor[] congDescs = td.getConglomerateDescriptors(); 309 boolean duplicate = false; 310 311 for (int i = 0; i < congDescs.length; i++) 312 { 313 ConglomerateDescriptor cd = congDescs[i]; 314 if ( ! cd.isIndex()) 315 continue; 316 IndexRowGenerator irg = cd.getIndexDescriptor(); 317 int[] bcps = irg.baseColumnPositions(); 318 boolean[] ia = irg.isAscending(); 319 int j = 0; 320 321 329 330 if ((bcps.length == baseColumnPositions.length) && 331 (irg.isUnique() || !unique) && 332 indexType.equals(irg.indexType())) 333 { 334 for (; j < bcps.length; j++) 335 { 336 if ((bcps[j] != baseColumnPositions[j]) || (ia[j] != isAscending[j])) 337 break; 338 } 339 } 340 341 if (j == baseColumnPositions.length) { 343 347 if (!isConstraint) 348 { 349 activation.addWarning( 350 StandardException.newWarning( 351 SQLState.LANG_INDEX_DUPLICATE, 352 cd.getConglomerateName())); 353 354 return; 355 } 356 357 conglomId = cd.getConglomerateNumber(); 359 indexRowGenerator = cd.getIndexDescriptor(); 360 conglomerateUUID = dd.getUUIDFactory().createUUID(); 363 duplicate = true; 364 break; 365 } 366 } 367 368 372 DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator(); 373 if (duplicate) 374 { 375 ConglomerateDescriptor cgd = 376 ddg.newConglomerateDescriptor(conglomId, indexName, true, 377 indexRowGenerator, isConstraint, 378 conglomerateUUID, td.getUUID(), sd.getUUID() ); 379 dd.addDescriptor(cgd, sd, DataDictionary.SYSCONGLOMERATES_CATALOG_NUM, false, tc); 380 ConglomerateDescriptorList cdl = 383 td.getConglomerateDescriptorList(); 384 cdl.add(cgd); 385 386 } 389 390 Properties indexProperties; 393 394 if (properties != null) 395 { 396 indexProperties = properties; 397 } 398 else 399 { 400 indexProperties = new Properties (); 401 } 402 403 indexProperties.put("baseConglomerateId", 405 Long.toString(td.getHeapConglomerateId())); 406 407 indexProperties.put("nUniqueColumns", 411 Integer.toString(unique ? baseColumnPositions.length : 412 baseColumnPositions.length + 1) 413 ); 414 415 indexProperties.put("rowLocationColumn", 417 Integer.toString(baseColumnPositions.length)); 418 419 indexProperties.put("nKeyFields", 421 Integer.toString(baseColumnPositions.length + 1)); 422 423 if (! duplicate) 425 { 426 indexRowGenerator = new IndexRowGenerator(indexType, unique, 427 baseColumnPositions, 428 isAscending, 429 baseColumnPositions.length); 430 } 431 432 438 439 rowSource = null; 440 sortId = 0; 441 boolean needToDropSort = false; 443 449 int bulkFetchSize = (forCreateTable) ? 1 : 16; 450 int numColumns = td.getNumberOfColumns(); 451 int approximateRowSize = 0; 452 453 FormatableBitSet bitSet = new FormatableBitSet(numColumns+1); 455 for (int index = 0; index < baseColumnPositions.length; index++) 456 { 457 bitSet.set(baseColumnPositions[index]); 458 } 459 FormatableBitSet zeroBasedBitSet = RowUtil.shift(bitSet, 1); 460 461 scan = tc.openGroupFetchScan( 463 td.getHeapConglomerateId(), 464 false, 0, TransactionController.MODE_TABLE, 467 TransactionController.ISOLATION_SERIALIZABLE, 468 zeroBasedBitSet, (DataValueDescriptor[]) null, 0, null, (DataValueDescriptor[]) null, 0); 475 baseRows = new ExecRow[bulkFetchSize]; 477 indexRows = new ExecIndexRow[bulkFetchSize]; 478 compactBaseRows = new ExecRow[bulkFetchSize]; 479 480 try 481 { 482 for (int i = 0; i < bulkFetchSize; i++) 484 { 485 baseRows[i] = activation.getExecutionFactory().getValueRow(maxBaseColumnPosition); 487 488 indexRows[i] = indexRowGenerator.getIndexRowTemplate(); 490 491 compactBaseRows[i] = activation.getExecutionFactory().getValueRow( 493 baseColumnPositions.length); 494 } 495 496 indexTemplateRow = indexRows[0]; 497 498 ColumnDescriptorList cdl = td.getColumnDescriptorList(); 500 int cdlSize = cdl.size(); 501 for (int index = 0, numSet = 0; index < cdlSize; index++) 502 { 503 if (! zeroBasedBitSet.get(index)) 504 { 505 continue; 506 } 507 numSet++; 508 ColumnDescriptor cd = (ColumnDescriptor) cdl.elementAt(index); 509 DataTypeDescriptor dts = cd.getType(); 510 511 512 for (int i = 0; i < bulkFetchSize; i++) 513 { 514 baseRows[i].setColumn(index + 1, 516 dts.getNull()); 517 compactBaseRows[i].setColumn(numSet, 518 baseRows[i].getColumn(index + 1)); 519 } 520 521 approximateRowSize += dts.getTypeId().getApproximateLengthInBytes(dts); 523 } 524 525 RowLocation rl[] = new RowLocation[bulkFetchSize]; 527 for (int i = 0; i < bulkFetchSize; i++) 528 { 529 rl[i] = scan.newRowLocationTemplate(); 530 531 indexRowGenerator.getIndexRow(compactBaseRows[i], rl[i], indexRows[i], bitSet); 533 } 534 535 537 if (duplicate) 538 return; 539 540 548 int numColumnOrderings; 549 SortObserver sortObserver = null; 550 if (unique) 551 { 552 numColumnOrderings = baseColumnPositions.length; 553 String indexOrConstraintName = indexName; 555 if (conglomerateUUID != null) 556 { 557 ConglomerateDescriptor cd = dd.getConglomerateDescriptor(conglomerateUUID); 558 if ((isConstraint) && (cd != null && cd.getUUID() != null && td != null)) 559 { 560 ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td, 561 cd.getUUID()); 562 indexOrConstraintName = conDesc.getConstraintName(); 563 } 564 } 565 sortObserver = new UniqueIndexSortObserver(true, isConstraint, 566 indexOrConstraintName, 567 indexTemplateRow, 568 true, 569 td.getName()); 570 } 571 else 572 { 573 numColumnOrderings = baseColumnPositions.length + 1; 574 sortObserver = new BasicSortObserver(true, false, 575 indexTemplateRow, 576 true); 577 } 578 ColumnOrdering[] order = new ColumnOrdering[numColumnOrderings]; 579 for (int i=0; i < numColumnOrderings; i++) 580 { 581 order[i] = new IndexColumnOrder(i, unique || i < numColumnOrderings - 1 582 ? isAscending[i] : true); 583 } 584 585 sortId = tc.createSort((Properties )null, 587 indexTemplateRow.getRowArrayClone(), 588 order, 589 sortObserver, 590 false, scan.getEstimatedRowCount(), 592 approximateRowSize ); 594 595 needToDropSort = true; 596 597 rowSource = loadSorter(baseRows, indexRows, tc, 601 scan, sortId, rl); 602 603 conglomId = tc.createAndLoadConglomerate( 604 indexType, 605 indexTemplateRow.getRowArray(), order, indexProperties, 608 TransactionController.IS_DEFAULT, rowSource, 610 (long[]) null); 611 612 } 613 finally 614 { 615 616 617 if (scan != null) 618 scan.close(); 619 620 621 if (rowSource != null) 622 rowSource.closeRowSource(); 623 624 628 if (needToDropSort) 629 tc.dropSort(sortId); 630 } 631 632 ConglomerateController indexController = 633 tc.openConglomerate( 634 conglomId, false, 0, TransactionController.MODE_TABLE, 635 TransactionController.ISOLATION_SERIALIZABLE); 636 637 if ( ! indexController.isKeyed()) 639 { 640 indexController.close(); 641 throw StandardException.newException(SQLState.LANG_NON_KEYED_INDEX, indexName, 642 indexType); 643 } 644 indexController.close(); 645 646 651 ConglomerateDescriptor cgd = 652 ddg.newConglomerateDescriptor(conglomId, indexName, true, 653 indexRowGenerator, isConstraint, 654 conglomerateUUID, td.getUUID(), sd.getUUID() ); 655 656 dd.addDescriptor(cgd, sd, DataDictionary.SYSCONGLOMERATES_CATALOG_NUM, false, tc); 657 658 ConglomerateDescriptorList cdl = td.getConglomerateDescriptorList(); 661 cdl.add(cgd); 662 663 CardinalityCounter cCount = (CardinalityCounter)rowSource; 664 long numRows; 665 if ((numRows = cCount.getRowCount()) > 0) 666 { 667 long[] c = cCount.getCardinality(); 668 for (int i = 0; i < c.length; i++) 669 { 670 StatisticsDescriptor statDesc = 671 new StatisticsDescriptor(dd, dd.getUUIDFactory().createUUID(), 672 cgd.getUUID(), td.getUUID(), "I", new StatisticsImpl(numRows, c[i]), 673 i + 1); 674 dd.addDescriptor(statDesc, null, 675 DataDictionary.SYSSTATISTICS_CATALOG_NUM, 676 true, tc); 677 } 678 } 679 } 680 681 683 ExecRow getIndexTemplateRow() 689 { 690 return indexTemplateRow; 691 } 692 693 700 private void statementExceptionCleanup( 701 ScanController scan, 702 ConglomerateController indexController) 703 throws StandardException 704 { 705 if (indexController != null) 706 { 707 indexController.close(); 708 } 709 if (scan != null) 710 { 711 scan.close(); 712 } 713 } 714 715 723 private RowLocationRetRowSource loadSorter(ExecRow[] baseRows, 724 ExecIndexRow[] indexRows, 725 TransactionController tc, 726 GroupFetchScanController scan, 727 long sortId, 728 RowLocation rl[]) 729 throws StandardException 730 { 731 SortController sorter; 732 long rowCount = 0; 733 734 sorter = tc.openSort(sortId); 735 736 try 737 { 738 int bulkFetchSize = baseRows.length; 741 742 if (SanityManager.DEBUG) 743 { 744 SanityManager.ASSERT(bulkFetchSize == indexRows.length, 745 "number of base rows and index rows does not match"); 746 SanityManager.ASSERT(bulkFetchSize == rl.length, 747 "number of base rows and row locations does not match"); 748 } 749 750 DataValueDescriptor[][] baseRowArray = new DataValueDescriptor[bulkFetchSize][]; 751 752 for (int i = 0; i < bulkFetchSize; i++) 753 baseRowArray[i] = baseRows[i].getRowArray(); 754 755 int bulkFetched = 0; 760 761 while ((bulkFetched = scan.fetchNextGroup(baseRowArray, rl)) > 0) 762 { 763 for (int i = 0; i < bulkFetched; i++) 764 { 765 sorter.insert(indexRows[i].getRowArray()); 766 rowCount++; 767 } 768 } 769 770 774 scan.setEstimatedRowCount(rowCount); 775 } 776 finally 777 { 778 sorter.close(); 779 } 780 781 return new CardinalityCounter(tc.openSortRowSource(sortId)); 782 } 783 } 784 785 | Popular Tags |