use of org.apache.derby.iapi.sql.execute.ExecRow in project derby by apache.
the class TemporaryRowHolderImpl method cloneRow.
/* Avoid materializing a stream just because it goes through a temp table.
* It is OK to have a stream in the temp table (in memory or spilled to
* disk). The assumption is that one stream does not appear in two rows.
* For "update", one stream can be in two rows and the materialization is
* done in UpdateResultSet. Note to future users of this class who may
* insert a stream into this temp holder:
* (1) As mentioned above, one un-materialized stream can't appear in two
* rows; you need to objectify it first otherwise.
* (2) If you need to retrieve an un-materialized stream more than once
* from the temp holder, you need to either materialize the stream
* the first time, or, if there's a memory constraint, in the first
* time create a RememberBytesInputStream with the byte holder being
* BackingStoreByteHolder, finish it, and reset it after usage.
* A third option is to create a stream clone, but this requires that
* the container handles are kept open until the streams have been
* drained.
*
* Beetle 4896.
*/
private ExecRow cloneRow(ExecRow inputRow) {
DataValueDescriptor[] cols = inputRow.getRowArray();
int ncols = cols.length;
ExecRow cloned = ((ValueRow) inputRow).cloneMe();
for (int i = 0; i < ncols; i++) {
if (cols[i] != null) {
/* Rows are 1-based, cols[] is 0-based */
cloned.setColumn(i + 1, cols[i].cloneHolder());
}
}
if (inputRow instanceof IndexValueRow)
return new IndexValueRow(cloned);
else
return cloned;
}
use of org.apache.derby.iapi.sql.execute.ExecRow in project derby by apache.
the class TemporaryRowHolderResultSet method getNewRSOnCurrentRow.
/**
* Whip up a new Temp ResultSet that has a single
* row. This row will either have all the columns from
* the current row of the passed resultset or a subset
* of the columns from the passed resulset. It all depends
* on what columns are needed by the passed trigger and what
* columns exist in the resulset. The Temp resulset
* should only have the columns required by the trigger.
*
* @param triggerd We are building Temp resultset for this trigger
* @param activation the activation
* @param rs the result set
* @param colsReadFromTable The passed resultset is composed of
* these columns. We will create a temp resultset which
* will have either all these columns or only a subset of
* these columns. It all depends on what columns are needed
* by the trigger. If this param is null, then that means that
* all the columns from the trigger table have been read into
* the passed resultset.
*
* @return a single row result set
*
* @exception StandardException on error
*/
public static TemporaryRowHolderResultSet getNewRSOnCurrentRow(TriggerDescriptor triggerd, Activation activation, CursorResultSet rs, int[] colsReadFromTable) throws StandardException {
TemporaryRowHolderImpl singleRow;
DataDictionary dd = activation.getLanguageConnectionContext().getDataDictionary();
// any column reading optimization to maintain backward compatibility
if (!dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_9, null)) {
singleRow = new TemporaryRowHolderImpl(activation, null, rs.getResultDescription());
singleRow.insert(rs.getCurrentRow());
return (TemporaryRowHolderResultSet) singleRow.getResultSet();
}
// Get columns referenced in trigger action through REFERENCING clause
int[] referencedColsInTriggerAction = triggerd.getReferencedColsInTriggerAction();
// Get trigger column. If null, then it means that all the columns
// have been read because this trigger can be fired for any of the
// columns in the table
int[] referencedColsInTrigger = triggerd.getReferencedCols();
if (// this means not all the columns are being read
(referencedColsInTrigger != null) && (triggerd.isRowTrigger() && referencedColsInTriggerAction != null && referencedColsInTriggerAction.length != 0)) {
// If we are here, then trigger is defined on specific columns and
// it has trigger action columns used through REFERENCING clause
// Make an array which is a superset of trigger columns and
// trigger action columns referenced through REFERENCING clause.
// This superset is what the trigger is looking for in it's
// resulset.
int[] colsInTrigger = supersetofAllColumns(referencedColsInTrigger, referencedColsInTriggerAction);
int colsCountInTrigger = colsInTrigger.length;
int[] colsReallyNeeded = new int[colsCountInTrigger];
// Here, we find out what columns make up the passed resulset
int[] actualColsReadFromTable;
if (// this means not all the columns are being read
colsReadFromTable != null)
actualColsReadFromTable = justTheRequiredColumnsPositions(colsReadFromTable);
else {
int colsInTriggerTable = triggerd.getTableDescriptor().getNumberOfColumns();
actualColsReadFromTable = new int[colsInTriggerTable];
for (int i = 1; i <= colsInTriggerTable; i++) actualColsReadFromTable[i - 1] = i;
}
// Now we have what columns make up the passed resulset and what
// columns are needed by the trigger. We will map a temporary
// resultset for the trigger out of the above information using
// the passed resultset
int indexInActualColsReadFromTable = 0;
for (int i = 0; i < colsCountInTrigger; i++) {
for (; indexInActualColsReadFromTable < actualColsReadFromTable.length; indexInActualColsReadFromTable++) {
/* Return 1-based key column position if column is in the key */
if (actualColsReadFromTable[indexInActualColsReadFromTable] == colsInTrigger[i]) {
colsReallyNeeded[i] = indexInActualColsReadFromTable + 1;
break;
}
}
}
singleRow = new TemporaryRowHolderImpl(activation, null, activation.getLanguageConnectionContext().getLanguageFactory().getResultDescription(rs.getResultDescription(), colsReallyNeeded));
ExecRow row = activation.getExecutionFactory().getValueRow(colsCountInTrigger);
for (int i = 0; i < colsCountInTrigger; i++) row.setColumn(i + 1, rs.getCurrentRow().getColumn(colsReallyNeeded[i]));
singleRow.insert(row);
} else {
singleRow = new TemporaryRowHolderImpl(activation, null, rs.getResultDescription());
singleRow.insert(rs.getCurrentRow());
}
return (TemporaryRowHolderResultSet) singleRow.getResultSet();
}
use of org.apache.derby.iapi.sql.execute.ExecRow in project derby by apache.
the class UpdateResultSet method runChecker.
void runChecker(boolean restrictCheckOnly) throws StandardException {
/*
** For a deferred update, make sure that there
** aren't any primary keys that were removed which
** are referenced.
*/
if (deferred && updatingReferencedKey) {
ExecRow deletedRow;
CursorResultSet deletedRows;
/*
** For each referenced key that was modified
*/
for (int i = 0; i < fkInfoArray.length; i++) {
if (fkInfoArray[i].type == FKInfo.FOREIGN_KEY) {
continue;
}
deletedRows = deletedRowHolder.getResultSet();
try {
/*
** For each delete row
*/
deletedRows.open();
while ((deletedRow = deletedRows.getNextRow()) != null) {
if (!foundRow(deletedRow, fkInfoArray[i].colArray, insertedRowHolder)) {
// Argument "1" below: If a PK referenced by an FK
// is deferred, require at least one to be present
// in the primary table since we have modified the
// row's PK, unless postCheck == true, in which the
// call to postChecks does the actual checking, and
// we need at least one row intact to fulfill the
// constraint.
riChecker.doRICheck(activation, i, deletedRow, restrictCheckOnly, 1);
}
}
if (restrictCheckOnly) {
riChecker.postCheck(i);
}
} finally {
deletedRows.close();
}
}
}
/*
** For a deferred update, make sure that there
** aren't any foreign keys that were added that
** aren't referenced.
*/
if (deferred && updatingForeignKey) {
ExecRow insertedRow;
CursorResultSet insertedRows;
/*
** For each foreign key that was modified
*/
for (int i = 0; i < fkInfoArray.length; i++) {
if (fkInfoArray[i].type == FKInfo.REFERENCED_KEY) {
continue;
}
insertedRows = insertedRowHolder.getResultSet();
try {
/*
** For each inserted row
*/
insertedRows.open();
while ((insertedRow = insertedRows.getNextRow()) != null) {
if (!foundRow(insertedRow, fkInfoArray[i].colArray, deletedRowHolder)) {
riChecker.doRICheck(activation, i, insertedRow, restrictCheckOnly, // N/A, not referenced key
0);
}
}
} finally {
insertedRows.close();
}
}
}
}
use of org.apache.derby.iapi.sql.execute.ExecRow 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();
}
}
}
use of org.apache.derby.iapi.sql.execute.ExecRow in project derby by apache.
the class NestedLoopJoinResultSet method getNextRowCore.
/**
* Return the requested values computed
* from the next row (if any) for which
* the restriction evaluates to true.
* <p>
* restriction parameters
* are evaluated for each row.
*
* @exception StandardException Thrown on error
* @exception StandardException ResultSetNotOpen thrown if closed
* @return the next row in the join result
*/
public ExecRow getNextRowCore() throws StandardException {
if (isXplainOnlyMode())
return null;
ExecRow result = null;
boolean haveRow = false;
boolean restrict = false;
int colInCtr;
int colOutCtr;
DataValueDescriptor restrictBoolean;
beginTime = getCurrentTimeMillis();
if (!isOpen)
throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
/* If we have a row from the left side and the right side is not open,
* then we get an error on the previous next, either on the next on
* the left or the open on the right. So, we do a next on the left
* and then open the right if that succeeds.
*/
if (!isRightOpen && leftRow != null) {
leftRow = leftResultSet.getNextRowCore();
if (leftRow == null) {
closeRight();
} else {
rowsSeenLeft++;
openRight();
}
}
while (leftRow != null && !haveRow) {
if (oneRowRightSide && returnedRowMatchingRightSide) {
rightRow = null;
returnedRowMatchingRightSide = false;
} else {
rightRow = rightResultSet.getNextRowCore();
/* If this is a NOT EXISTS join, we just need to reverse the logic
* of EXISTS join. To make the implementation simple, we create a
* right side template, which is never really needed. (beetle 5173)
*/
if (notExistsRightSide) {
if (// none satisfied
rightRow == null)
// then we are
rightRow = rightTemplate;
else
rightRow = null;
}
returnedRowMatchingRightSide = (rightRow != null);
}
if (rightRow == null) {
/* Current scan on right is exhausted. Need to close old scan
* and open new scan with new "parameters". openRight()
* will reopen if already open.
*/
leftRow = leftResultSet.getNextRowCore();
if (leftRow == null) {
closeRight();
} else {
rowsSeenLeft++;
openRight();
}
} else {
rowsSeenRight++;
if (restriction != null) {
restrictBoolean = (DataValueDescriptor) restriction.invoke(activation);
// if the result is null, we make it false --
// so the row won't be returned.
restrict = (!restrictBoolean.isNull()) && restrictBoolean.getBoolean();
if (!restrict) {
/* Update the run time statistics */
rowsFiltered++;
continue;
}
}
/* Merge the rows, doing just in time allocation for mergedRow.
* (By convention, left Row is to left of right Row.)
*/
if (mergedRow == null) {
mergedRow = getExecutionFactory().getValueRow(leftNumCols + rightNumCols);
}
for (colInCtr = 1, colOutCtr = 1; colInCtr <= leftNumCols; colInCtr++, colOutCtr++) {
DataValueDescriptor src_col = leftRow.getColumn(colInCtr);
// (DERBY-3650).
if (src_col != null && src_col.hasStream()) {
src_col = src_col.cloneValue(false);
}
mergedRow.setColumn(colOutCtr, src_col);
}
if (!notExistsRightSide) {
for (colInCtr = 1; colInCtr <= rightNumCols; colInCtr++, colOutCtr++) {
DataValueDescriptor src_col = rightRow.getColumn(colInCtr);
// (DERBY-3650).
if (src_col != null && src_col.hasStream()) {
src_col = src_col.cloneValue(false);
}
mergedRow.setColumn(colOutCtr, src_col);
}
}
setCurrentRow(mergedRow);
haveRow = true;
}
}
/* Do we have a row to return? */
if (haveRow) {
result = mergedRow;
rowsReturned++;
} else {
clearCurrentRow();
}
nextTime += getElapsedMillis(beginTime);
return result;
}
Aggregations