use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class BTreeController method load.
/**
* Load rows from rowSource into the opened btree.
* <p>
* Efficiently load rows into the already opened btree. The btree must
* be table locked, as no row locks will be requested by this routine.
* On exit from this routine the conglomerate will be closed (on both
* error or success).
* <p>
* This routine does an almost bottom up build of a btree. It assumes
* all rows arrive in sorted order, and inserts them directly into the
* next (to the right) spot in the current leaf until there is no space.
* Then it calls the generic split code to add the next leaf (RESOLVE -
* in the future we could optimize this to split bottom up rather than
* top down for create index).
*
* @exception StandardException Standard exception policy. If conglomerate
* supports uniqueness checks and has been
* created to disallow duplicates, and one of
* the rows being loaded had key columns which
* were duplicate of a row already in the
* conglomerate, then raise
* SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION.
*
* @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#load
*/
public long load(TransactionManager xact_manager, boolean createConglom, RowLocationRetRowSource rowSource) throws StandardException {
long num_rows_loaded = 0;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(createConglom, "Cannot load a btree incrementally - it must either be entirely logged, or entirely not logged. Doesn't make sense to log only the allocation when one cannot guarantee to not touch any pre-existing pages");
}
if (scratch_template == null) {
scratch_template = runtime_mem.get_template(getRawTran());
}
LeafControlRow current_leaf = null;
try {
// Btree must just have been created and empty, so there must
// be one root leaf page which is empty except for the control row.
current_leaf = (LeafControlRow) ControlRow.get(this, BTree.ROOTPAGEID);
int current_insert_slot = 1;
if (SanityManager.DEBUG) {
// root must be empty except for the control row.
SanityManager.ASSERT(current_leaf.page.recordCount() == 1);
}
// now loop thru the row source and insert into the btree
FormatableBitSet validColumns = rowSource.getValidColumns();
// get the next row and its valid columns from the rowSource
DataValueDescriptor[] row;
while ((row = rowSource.getNextRowFromRowSource()) != null) {
num_rows_loaded++;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(validColumns == null, "Does not support partial row");
}
while (true) {
if (do_load_insert(row, current_leaf, current_insert_slot)) {
// row inserted successfully.
break;
} else {
// if insert fails, do a split pass. There is an edge
// case where multiple split passes are necessary if
// branch splits are necessary, thus the loop. It is
// most likely that only a single split pass will be
// necessary.
current_leaf = do_load_split(row, current_leaf);
current_insert_slot = current_leaf.page.recordCount();
}
}
current_insert_slot++;
}
current_leaf.release();
current_leaf = null;
// Loading done, must flush all pages to disk since it is unlogged.
if (!this.getConglomerate().isTemporary())
container.flushContainer();
} finally {
this.close();
}
return (num_rows_loaded);
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class DeleteOperation method writeOptionalDataToBuffer.
/**
* if logical undo, writes out the row that was deleted
*
* @exception IOException Can be thrown by any of the methods of ObjectOutput
* @exception StandardException Standard Derby policy.
*/
private void writeOptionalDataToBuffer(RawTransaction t) throws StandardException, IOException {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(this.page != null);
}
DynamicByteArrayOutputStream logBuffer = t.getLogBuffer();
int optionalDataStart = logBuffer.getPosition();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(optionalDataStart == 0, "Buffer for writing the optional data should start at position 0");
}
if (undo != null)
this.page.logRecord(doMeSlot, BasePage.LOG_RECORD_DEFAULT, recordId, (FormatableBitSet) null, logBuffer, (RecordHandle) null);
int optionalDataLength = logBuffer.getPosition() - optionalDataStart;
if (SanityManager.DEBUG) {
if (optionalDataLength != logBuffer.getUsed())
SanityManager.THROWASSERT("wrong optional data length, optionalDataLength = " + optionalDataLength + ", logBuffer.getUsed() = " + logBuffer.getUsed());
}
// set the position to the beginning of the buffer
logBuffer.setPosition(optionalDataStart);
this.preparedLog = new ByteArray(logBuffer.getByteArray(), optionalDataStart, optionalDataLength);
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class TemporaryRowHolderResultSet method setupPositionBasedScan.
// open the scan of the temporary heap and the position index
private void setupPositionBasedScan(long position) throws StandardException {
// incase nothing is inserted yet into the temporary row holder
if (holder.getTemporaryConglomId() == 0)
return;
if (heapCC == null) {
heapCC = tc.openConglomerate(holder.getTemporaryConglomId(), false, 0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
}
currentRow = rowArray[0].getNewNullRow();
indexRow = new DataValueDescriptor[2];
indexRow[0] = new SQLLongint(position);
indexRow[1] = heapCC.newRowLocationTemplate();
DataValueDescriptor[] searchRow = new DataValueDescriptor[1];
searchRow[0] = new SQLLongint(position);
if (indexsc == null) {
indexsc = tc.openScan(positionIndexConglomId, // don't hold open across commit
false, // for read
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, // all fields as objects
(FormatableBitSet) null, // start position - first row
searchRow, // startSearchOperation
ScanController.GE, // scanQualifier,
null, // stop position - through last row
null, // stopSearchOperation
ScanController.GT);
} else {
indexsc.reopenScan(// startKeyValue
searchRow, // startSearchOp
ScanController.GE, // qualifier
null, // stopKeyValue
null, // stopSearchOp
ScanController.GT);
}
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class UpdateResultSet method collectAffectedRows.
public boolean collectAffectedRows() throws StandardException {
boolean rowsFound = false;
row = getNextRowCore(sourceResultSet);
if (row != null)
rowsFound = true;
else {
activation.addWarning(StandardException.newWarning(SQLState.LANG_NO_ROW_FOUND));
}
// beetle 3865, update cursor use index.
TableScanResultSet tableScan = (TableScanResultSet) activation.getForUpdateIndexScan();
boolean notifyCursor = (tableScan != null);
boolean checkStream = (deferred && rowsFound && !constants.singleRowSource);
FormatableBitSet streamCols = (checkStream ? checkStreamCols() : null);
checkStream = (streamCols != null);
while (row != null) {
evaluateGenerationClauses(generationClauses, activation, sourceResultSet, row, true);
/*
** If we're doing deferred update, write the new row and row
** location to the temporary conglomerate. If we're not doing
** deferred update, update the permanent conglomerates now
** using the RowChanger.
*/
if (deferred) {
/*
** If we have a before trigger, we must evaluate the
** check constraint after we have executed the trigger.
** Note that we have compiled checkGM accordingly (to
** handle the different row shape if we are evaluating
** against the input result set or a temporary row holder
** result set).
*/
if (triggerInfo == null) {
boolean allOk = evaluateCheckConstraints();
if (!allOk) {
DataValueDescriptor[] rw = row.getRowArray();
SQLRef r = (SQLRef) rw[rw.length - 1];
RowLocation baseRowLocation = (RowLocation) r.getObject();
deferredChecks = DeferredConstraintsMemory.rememberCheckViolations(lcc, constants.targetUUID, constants.getSchemaName(), constants.getTableName(), deferredChecks, violatingCheckConstraints, baseRowLocation, new CheckInfo[1]);
}
}
/*
** We are going to only save off the updated
** columns and the RID. For a trigger, all columns
** were marked as needed so we'll copy them all.
*/
RowUtil.copyRefColumns(deferredTempRow, row, numberOfBaseColumns, numberOfBaseColumns + 1);
if (checkStream)
objectifyStream(deferredTempRow, streamCols);
insertedRowHolder.insert(deferredTempRow);
/*
** Grab a copy of the row to delete. We are
** going to use this for deferred RI checks.
*/
if (beforeUpdateCopyRequired) {
RowUtil.copyRefColumns(oldDeletedRow, row, numberOfBaseColumns);
deletedRowHolder.insert(oldDeletedRow);
}
/*
** If we haven't already, lets get a template to
** use as a template for our rescan of the base table.
** Do this now while we have a real row to use
** as a copy.
**
** There is one less column in the base row than
** there is in source row, because the base row
** doesn't contain the row location.
*/
if (deferredBaseRow == null) {
deferredBaseRow = RowUtil.getEmptyValueRow(numberOfBaseColumns, lcc);
RowUtil.copyCloneColumns(deferredBaseRow, row, numberOfBaseColumns);
/*
** While we're here, let's also create a sparse row for
** fetching from the store.
*/
deferredSparseRow = makeDeferredSparseRow(deferredBaseRow, baseRowReadList, lcc);
}
} else {
boolean allOk = evaluateCheckConstraints();
/* Get the RowLocation to update
* NOTE - Column #s in the Row are 1 based.
*/
RowLocation baseRowLocation = (RowLocation) (row.getColumn(resultWidth)).getObject();
if (!allOk) {
deferredChecks = DeferredConstraintsMemory.rememberCheckViolations(lcc, constants.targetUUID, constants.getSchemaName(), constants.getTableName(), deferredChecks, violatingCheckConstraints, baseRowLocation, new CheckInfo[1]);
}
RowUtil.copyRefColumns(newBaseRow, row, numberOfBaseColumns, numberOfBaseColumns);
if (riChecker != null) {
/*
** Make sure all foreign keys in the new row
** are maintained. Note that we don't bother
** checking primary/unique keys that are referenced
** here. The reason is that if we are updating
** a referenced key, we'll be updating in deferred
** mode, so we wont get here.
*/
riChecker.doFKCheck(activation, newBaseRow);
}
sourceResultSet.updateRow(newBaseRow, rowChanger);
rowChanger.updateRow(row, newBaseRow, baseRowLocation);
// beetle 3865, update cursor use index.
if (notifyCursor)
notifyForUpdateCursor(row.getRowArray(), newBaseRow.getRowArray(), baseRowLocation, tableScan);
}
rowCount++;
// No need to do a next on a single row source
if (constants.singleRowSource) {
row = null;
} else {
row = getNextRowCore(sourceResultSet);
}
}
if (rowCount == 1 && constants.hasAutoincrement())
lcc.setIdentityValue(identityVal);
return rowsFound;
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class UpdateResultSet method updateDeferredRows.
void updateDeferredRows() throws StandardException {
if (deferred) {
// we already have everything locked
deferredBaseCC = tc.openCompiledConglomerate(false, (TransactionController.OPENMODE_SECONDARY_LOCKED | TransactionController.OPENMODE_FORUPDATE), lockMode, TransactionController.ISOLATION_SERIALIZABLE, constants.heapSCOCI, heapDCOCI);
CursorResultSet rs = insertedRowHolder.getResultSet();
try {
/*
** We need to do a fetch doing a partial row
** read. We need to shift our 1-based bit
** set to a zero based bit set like the store
** expects.
*/
FormatableBitSet readBitSet = RowUtil.shift(baseRowReadList, 1);
ExecRow deferredTempRow2;
rs.open();
while ((deferredTempRow2 = rs.getNextRow()) != null) {
/*
** Check the constraint now if we have triggers.
** Otherwise we evaluated them as we read the
** rows in from the source.
*/
boolean allOk = true;
if (triggerInfo != null) {
sourceResultSet.setCurrentRow(deferredTempRow);
allOk = evaluateCheckConstraints();
}
/*
** The last column is a Ref, which contains a
** RowLocation.
*/
DataValueDescriptor rlColumn = deferredTempRow2.getColumn(numberOfBaseColumns + 1);
RowLocation baseRowLocation = (RowLocation) (rlColumn).getObject();
if (!allOk) {
deferredChecks = DeferredConstraintsMemory.rememberCheckViolations(lcc, constants.targetUUID, constants.getSchemaName(), constants.getTableName(), deferredChecks, violatingCheckConstraints, baseRowLocation, new CheckInfo[1]);
}
/* Get the base row at the given RowLocation */
boolean row_exists = deferredBaseCC.fetch(baseRowLocation, deferredSparseRow.getRowArray(), readBitSet);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(row_exists, "did not find base row in deferred update");
}
/*
** Copy the columns from the temp row to the base row.
** The base row has fewer columns than the temp row,
** because it doesn't contain the row location.
*/
RowUtil.copyRefColumns(newBaseRow, deferredTempRow2, numberOfBaseColumns);
rowChanger.updateRow(deferredBaseRow, newBaseRow, baseRowLocation);
}
} finally {
sourceResultSet.clearCurrentRow();
rs.close();
}
}
}
Aggregations