use of org.apache.derby.iapi.store.access.SortController in project derby by apache.
the class InsertResultSet method emptyIndexes.
/**
* Empty the indexes after doing a bulk insert replace
* where the table has 0 rows after the replace.
* RESOLVE: This method is ugly! Prior to 2.0, we simply
* scanned back across the table to build the indexes. We
* changed this in 2.0 to populate the sorters via a call back
* as we populated the table. Doing a 0 row replace into a
* table with indexes is a degenerate case, hence we allow
* ugly and unoptimized code.
*
* @exception StandardException Thrown on failure
*/
private void emptyIndexes(long newHeapConglom, InsertConstantAction constants, TableDescriptor td, DataDictionary dd, ExecRow fullTemplate) throws StandardException {
int numIndexes = constants.irgs.length;
ExecIndexRow[] idxRows = new ExecIndexRow[numIndexes];
ExecRow baseRows;
ColumnOrdering[][] order = new ColumnOrdering[numIndexes][];
int numColumns = td.getNumberOfColumns();
collation = new int[numIndexes][];
// Create the BitSet for mapping the partial row to the full row
FormatableBitSet bitSet = new FormatableBitSet(numColumns + 1);
// Need to check each index for referenced columns
int numReferencedColumns = 0;
for (int index = 0; index < numIndexes; index++) {
int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
for (int bcp = 0; bcp < baseColumnPositions.length; bcp++) {
if (!bitSet.get(baseColumnPositions[bcp])) {
bitSet.set(baseColumnPositions[bcp]);
numReferencedColumns++;
}
}
}
// We can finally create the partial base row
baseRows = activation.getExecutionFactory().getValueRow(numReferencedColumns);
// Fill in each base row with nulls of the correct data type
int colNumber = 0;
for (int index = 0; index < numColumns; index++) {
if (bitSet.get(index + 1)) {
colNumber++;
// NOTE: 1-based column numbers
baseRows.setColumn(colNumber, fullTemplate.getColumn(index + 1).cloneValue(false));
}
}
needToDropSort = new boolean[numIndexes];
sortIds = new long[numIndexes];
/* Do the initial set up before scanning the heap.
* For each index, build a single index row and a sorter.
*/
for (int index = 0; index < numIndexes; index++) {
// create a single index row template for each index
idxRows[index] = constants.irgs[index].getIndexRowTemplate();
// Get an index row based on the base row
// (This call is only necessary here because we need to pass a
// template to the sorter.)
constants.irgs[index].getIndexRow(baseRows, rl, idxRows[index], bitSet);
/* For non-unique indexes, we order by all columns + the RID.
* For unique indexes, we just order by the columns.
* We create a unique index observer for unique indexes
* so that we can catch duplicate key
*/
ConglomerateDescriptor cd;
// Get the ConglomerateDescriptor for the index
cd = td.getConglomerateDescriptor(constants.indexCIDS[index]);
int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
boolean[] isAscending = constants.irgs[index].isAscending();
int numColumnOrderings;
SortObserver sortObserver;
final IndexRowGenerator indDes = cd.getIndexDescriptor();
if (indDes.isUnique() || indDes.isUniqueDeferrable()) {
numColumnOrderings = indDes.isUnique() ? baseColumnPositions.length : baseColumnPositions.length + 1;
String indexOrConstraintName = cd.getConglomerateName();
boolean deferred = false;
boolean uniqueDeferrable = false;
UUID uniqueDeferrableConstraintId = null;
if (cd.isConstraint()) {
// so, the index is backing up a constraint
ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td, cd.getUUID());
indexOrConstraintName = conDesc.getConstraintName();
deferred = lcc.isEffectivelyDeferred(lcc.getCurrentSQLSessionContext(activation), conDesc.getUUID());
uniqueDeferrable = conDesc.deferrable();
uniqueDeferrableConstraintId = conDesc.getUUID();
}
sortObserver = new UniqueIndexSortObserver(lcc, uniqueDeferrableConstraintId, // don't clone rows
false, uniqueDeferrable, deferred, indexOrConstraintName, idxRows[index], true, td.getName());
} else {
numColumnOrderings = baseColumnPositions.length + 1;
sortObserver = new BasicSortObserver(false, false, idxRows[index], true);
}
order[index] = new ColumnOrdering[numColumnOrderings];
for (int ii = 0; ii < isAscending.length; ii++) {
order[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
}
if (numColumnOrderings > isAscending.length) {
order[index][isAscending.length] = new IndexColumnOrder(isAscending.length);
}
// create the sorters
sortIds[index] = tc.createSort((Properties) null, idxRows[index].getRowArrayClone(), order[index], sortObserver, // not in order
false, // est rows
rowCount, // est row size, -1 means no idea
-1);
needToDropSort[index] = true;
}
// Populate sorters and get the output of each sorter into a row
// source. The sorters have the indexed columns only and the columns
// are in the correct order.
rowSources = new RowLocationRetRowSource[numIndexes];
// Fill in the RowSources
SortController[] sorter = new SortController[numIndexes];
for (int index = 0; index < numIndexes; index++) {
sorter[index] = tc.openSort(sortIds[index]);
sorter[index].completedInserts();
rowSources[index] = tc.openSortRowSource(sortIds[index]);
}
long[] newIndexCongloms = new long[numIndexes];
// Populate each index
for (int index = 0; index < numIndexes; index++) {
ConglomerateController indexCC;
Properties properties = new Properties();
ConglomerateDescriptor cd;
// Get the ConglomerateDescriptor for the index
cd = td.getConglomerateDescriptor(constants.indexCIDS[index]);
// Build the properties list for the new conglomerate
indexCC = tc.openCompiledConglomerate(false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, constants.indexSCOCIs[index], indexDCOCIs[index]);
// Get the properties on the old index
indexCC.getInternalTablePropertySet(properties);
/* Create the properties that language supplies when creating the
* the index. (The store doesn't preserve these.)
*/
int indexRowLength = idxRows[index].nColumns();
properties.put("baseConglomerateId", Long.toString(newHeapConglom));
if (cd.getIndexDescriptor().isUnique()) {
properties.put("nUniqueColumns", Integer.toString(indexRowLength - 1));
} else {
properties.put("nUniqueColumns", Integer.toString(indexRowLength));
}
if (cd.getIndexDescriptor().isUniqueWithDuplicateNulls() && !cd.getIndexDescriptor().hasDeferrableChecking()) {
properties.put("uniqueWithDuplicateNulls", Boolean.toString(true));
}
properties.put("rowLocationColumn", Integer.toString(indexRowLength - 1));
properties.put("nKeyFields", Integer.toString(indexRowLength));
indexCC.close();
collation[index] = constants.irgs[index].getColumnCollationIds(td.getColumnDescriptorList());
// We can finally drain the sorter and rebuild the index
// Populate the index.
newIndexCongloms[index] = tc.createAndLoadConglomerate("BTREE", idxRows[index].getRowArray(), // default column sort order
null, collation[index], properties, TransactionController.IS_DEFAULT, rowSources[index], (long[]) null);
/* Update the DataDictionary
*
* Update sys.sysconglomerates with new conglomerate #, if the
* conglomerate is shared by duplicate indexes, all the descriptors
* for those indexes need to be updated with the new number.
*/
dd.updateConglomerateDescriptor(td.getConglomerateDescriptors(constants.indexCIDS[index]), newIndexCongloms[index], tc);
// Drop the old conglomerate
tc.dropConglomerate(constants.indexCIDS[index]);
}
}
use of org.apache.derby.iapi.store.access.SortController in project derby by apache.
the class RAMTransaction method closeControllers.
/**
************************************************************************
* Private/Protected methods of This class:
**************************************************************************
*/
// XXX (nat) currently closes all controllers.
protected void closeControllers(boolean closeHeldControllers) throws StandardException {
if (!scanControllers.isEmpty()) {
// loop from end to beginning, removing scans which are not held.
for (int i = scanControllers.size() - 1; i >= 0; i--) {
ScanManager sc = scanControllers.get(i);
if (sc.closeForEndTransaction(closeHeldControllers)) {
// TODO - now counting on scan's removing themselves by
// calling the closeMe() method.
/* scanControllers.removeElementAt(i); */
}
}
if (closeHeldControllers) {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(scanControllers.isEmpty());
}
// just to make sure everything has been closed and removed.
scanControllers.clear();
}
}
if (!conglomerateControllers.isEmpty()) {
// loop from end to beginning, removing scans which are not held.
for (int i = conglomerateControllers.size() - 1; i >= 0; i--) {
ConglomerateController cc = conglomerateControllers.get(i);
if (cc.closeForEndTransaction(closeHeldControllers)) {
// TODO - now counting on cc's removing themselves by
// calling the closeMe() method.
/* conglomerateControllers.removeElementAt(i); */
}
}
if (closeHeldControllers) {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(scanControllers.isEmpty());
}
// just to make sure everything has been closed and removed.
conglomerateControllers.clear();
}
}
if ((sortControllers != null) && !sortControllers.isEmpty()) {
if (closeHeldControllers) {
// element from the list.
for (int i = sortControllers.size() - 1; i >= 0; i--) {
SortController sc = sortControllers.get(i);
sc.completedInserts();
}
sortControllers.clear();
}
}
if ((sorts != null) && (!sorts.isEmpty())) {
if (closeHeldControllers) {
// element from the list.
for (int i = sorts.size() - 1; i >= 0; i--) {
Sort sort = sorts.get(i);
if (sort != null)
sort.drop(this);
}
sorts.clear();
freeSortIds.clear();
}
}
}
use of org.apache.derby.iapi.store.access.SortController in project derby by apache.
the class RAMTransaction method debugOpened.
/**
* Return a string with debug information about opened congloms/scans/sorts.
* <p>
* Return a string with debugging information about current opened
* congloms/scans/sorts which have not been close()'d.
* Calls to this routine are only valid under code which is conditional
* on SanityManager.DEBUG.
* <p>
*
* @return String with debugging information.
*
* @exception StandardException Standard exception policy.
*/
public String debugOpened() throws StandardException {
String str = null;
if (SanityManager.DEBUG) {
str = "";
for (Iterator<ScanManager> it = scanControllers.iterator(); it.hasNext(); ) {
ScanController sc = it.next();
str += "open scan controller: " + sc + "\n";
}
for (Iterator<ConglomerateController> it = conglomerateControllers.iterator(); it.hasNext(); ) {
ConglomerateController cc = (ConglomerateController) it.next();
str += "open conglomerate controller: " + cc + "\n";
}
if (sortControllers != null) {
for (Iterator<SortController> it = sortControllers.iterator(); it.hasNext(); ) {
SortController sc = it.next();
str += "open sort controller: " + sc + "\n";
}
}
if (sorts != null) {
for (int i = 0; i < sorts.size(); i++) {
Sort sort = sorts.get(i);
if (sort != null) {
str += "sorts created by createSort() in current xact:" + sort + "\n";
}
}
}
if (tempCongloms != null) {
for (Iterator<Long> it = tempCongloms.keySet().iterator(); it.hasNext(); ) {
Long conglomId = it.next();
Conglomerate c = tempCongloms.get(conglomId);
str += "temp conglomerate id = " + conglomId + ": " + c;
}
}
}
return (str);
}
use of org.apache.derby.iapi.store.access.SortController in project derby by apache.
the class RAMTransaction method openSort.
/**
* @see TransactionController#openSort
* @exception StandardException Standard error policy.
*/
public SortController openSort(long id) throws StandardException {
Sort sort;
// if it doesn't exist.
if (sorts == null || id >= sorts.size() || (sort = (sorts.get((int) id))) == null) {
throw StandardException.newException(SQLState.AM_NO_SUCH_SORT, id);
}
// Open it.
SortController sc = sort.open(this);
// Keep track of it so we can release on close.
if (sortControllers == null)
sortControllers = new ArrayList<SortController>();
sortControllers.add(sc);
return sc;
}
use of org.apache.derby.iapi.store.access.SortController in project derby by apache.
the class CreateIndexConstantAction method loadSorter.
/**
* Scan the base conglomerate and insert the keys into a sorter,
* returning a rowSource on the sorter.
*
* @return RowSource on the sorted index keys.
*
* @exception StandardException thrown on error
*/
private RowLocationRetRowSource loadSorter(ExecRow[] baseRows, ExecIndexRow[] indexRows, TransactionController tc, GroupFetchScanController scan, long sortId, RowLocation[] rl) throws StandardException {
SortController sorter;
long rowCount = 0;
sorter = tc.openSort(sortId);
try {
// Step through all the rows in the base table
// prepare an array or rows for bulk fetch
int bulkFetchSize = baseRows.length;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(bulkFetchSize == indexRows.length, "number of base rows and index rows does not match");
SanityManager.ASSERT(bulkFetchSize == rl.length, "number of base rows and row locations does not match");
}
DataValueDescriptor[][] baseRowArray = new DataValueDescriptor[bulkFetchSize][];
for (int i = 0; i < bulkFetchSize; i++) baseRowArray[i] = baseRows[i].getRowArray();
// rl[i] and baseRowArray[i] and indexRows[i] are all tied up
// beneath the surface. Fetching the base row and row location
// from the table scan will automagically set up the indexRow
// fetchNextGroup will return how many rows are actually fetched.
int bulkFetched;
while ((bulkFetched = scan.fetchNextGroup(baseRowArray, rl)) > 0) {
for (int i = 0; i < bulkFetched; i++) {
sorter.insert(indexRows[i].getRowArray());
rowCount++;
}
}
/*
** We've just done a full scan on the heap, so set the number
** of rows so the optimizer will have an accurate count.
*/
scan.setEstimatedRowCount(rowCount);
} finally {
sorter.completedInserts();
}
return new CardinalityCounter(tc.openSortRowSource(sortId));
}
Aggregations