ArrayInputStream dataIn,
StoredRecordHeader recordHeader,
RecordHandle recordToLock)
throws StandardException, IOException
{
ErrorObjectInput inUserCode = null;
try
{
// Get the number of columns in the row.
int numberFields = recordHeader.getNumberFields();
int startColumn = recordHeader.getFirstField();
if (startColumn > max_colid)
{
// done if the startColumn is higher than highest column.
return true;
}
// For each column in the row, restore the column from
// the corresponding field in the record. If the field
// is missing or not set, set the column to null.
int highestColumnOnPage = numberFields + startColumn;
int vColsSize = (vCols == null ) ? 0 : vCols.length;
int offset_to_field_data = dataIn.getPosition();
for (int columnId = startColumn; columnId <= max_colid; columnId++)
{
// skip any "existing" columns not requested, or requested cols
// that have already been read.
if (((vCols != null) &&
(!(vColsSize > columnId && (vCols[columnId] != 0)))) ||
((mCols != null) && (mCols[columnId] != 0)))
{
if (columnId < highestColumnOnPage)
{
// If the field exists in the row on the page, but the
// partial row being returned does not include it,
// skip the field ...
offset_to_field_data +=
StoredFieldHeader.readTotalFieldLength(
pageData, offset_to_field_data);
}
continue;
}
else if (columnId < highestColumnOnPage)
{
// the column is on this page.
// read the field header
// read the status byte.
int fieldStatus =
StoredFieldHeader.readStatus(
pageData, offset_to_field_data);
// read the field data length, position on 1st byte of data
int fieldDataLength =
StoredFieldHeader.readFieldLengthAndSetStreamPosition(
pageData,
offset_to_field_data +
StoredFieldHeader.STORED_FIELD_HEADER_STATUS_SIZE,
fieldStatus,
slotFieldSize,
dataIn);
if (SanityManager.DEBUG)
{
SanityManager.ASSERT(
!StoredFieldHeader.isExtensible(fieldStatus),
"extensible fields not supported yet");
}
Object column = row[columnId];
OverflowInputStream overflowIn = null;
// SRW-DJD code assumes non-extensible case ...
if ((fieldStatus & StoredFieldHeader.FIELD_NONEXISTENT) !=
StoredFieldHeader.FIELD_NONEXISTENT)
{
// normal path - field exists.
boolean isOverflow =
((fieldStatus &
StoredFieldHeader.FIELD_OVERFLOW) != 0);
if (isOverflow)
{
// A fetched long column is returned as a stream
long overflowPage =
CompressedNumber.readLong((InputStream) dataIn);
int overflowId =
CompressedNumber.readInt((InputStream) dataIn);
// Prepare the stream for results...
// create the byteHolder the size of a page, so,
// that it will fit the field Data that would fit
// on a page.
MemByteHolder byteHolder =
new MemByteHolder(pageData.length);
overflowIn = new OverflowInputStream(
byteHolder, owner, overflowPage,
overflowId, recordToLock);
}
// Deal with Object columns
if (column instanceof DataValueDescriptor)
{
DataValueDescriptor sColumn =
(DataValueDescriptor) column;
// is the column null ?
if ((fieldStatus &
StoredFieldHeader.FIELD_NULL) == 0)
{
// the field is not null.
// set the limit for the user read
if (!isOverflow)
{
// normal, non-overflow column case.
dataIn.setLimit(fieldDataLength);
inUserCode = dataIn;
sColumn.readExternalFromArray(dataIn);
inUserCode = null;
int unread = dataIn.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(dataIn, unread);
}
else
{
// column being fetched is a long column.
FormatIdInputStream newIn =
new FormatIdInputStream(overflowIn);
// long columns are fetched as a stream.
boolean fetchStream = true;
if (!(sColumn instanceof StreamStorable))
{
fetchStream = false;
}
if (fetchStream)
{
((StreamStorable) sColumn).setStream(
newIn);
}
else
{
inUserCode = newIn;
sColumn.readExternal(newIn);
inUserCode = null;
}
}
}
else
{
sColumn.restoreToNull();
}
}
else
{
// At this point only non-Storable columns.
if (StoredFieldHeader.isNull(fieldStatus))
{
// Only Storables can be null ...
throw StandardException.newException(
SQLState.DATA_NULL_STORABLE_COLUMN,
Integer.toString(columnId));
}
// This is a non-extensible field, which means the
// caller must know the correct type and thus the
// element in row is the correct type or null. It
// must be Serializable.
//
// We do not support Externalizable here.
dataIn.setLimit(fieldDataLength);
inUserCode = dataIn;
// RESOLVE (no non-storables?)
row[columnId] = (Object) dataIn.readObject();
inUserCode = null;
int unread = dataIn.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(dataIn, unread);
}
}
else
{
// column is non-existent.
if (column instanceof DataValueDescriptor)
{
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
}
else
{
row[columnId] = null;
}
}
// move the counter to point to beginning of next field.
offset_to_field_data = dataIn.getPosition();
}
else
{
// field is non-existent
Object column = row[columnId];
if (column instanceof DataValueDescriptor)
{
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
}
else
{
row[columnId] = null;
}
}
}
// if the last column on this page is bigger than the highest
// column we are looking for, then we are done restoring the record.
if ((numberFields + startColumn) > max_colid)
return true;
else
return false;
}
catch (IOException ioe)
{
// an exception during the restore of a user column, this doesn't
// make the database corrupt, just that this field is inaccessable
if (inUserCode != null)
{
dataIn.clearLimit();
if (ioe instanceof EOFException)
{
if (SanityManager.DEBUG)
{
SanityManager.DEBUG_PRINT("DEBUG_TRACE",
"StoredPage - EOF while restoring record: " +
recordHeader +
"Page dump = " + this);
}
// going beyond the limit in a DataInput class results in
// an EOFException when it sees the -1 from a read
throw StandardException.newException(
SQLState.DATA_STORABLE_READ_MISMATCH,
ioe, inUserCode.getErrorInfo());
}
// some SQLData error reporting
Exception ne = inUserCode.getNestedException();
if (ne != null)
{
if (ne instanceof InstantiationException)
{
throw StandardException.newException(
SQLState.DATA_SQLDATA_READ_INSTANTIATION_EXCEPTION,
ne, inUserCode.getErrorInfo());
}
if (ne instanceof IllegalAccessException)
{
throw StandardException.newException(
SQLState.DATA_SQLDATA_READ_ILLEGAL_ACCESS_EXCEPTION,
ne, inUserCode.getErrorInfo());
}
if (ne instanceof StandardException)
{
throw (StandardException) ne;
}
}
throw StandardException.newException(
SQLState.DATA_STORABLE_READ_EXCEPTION,
ioe, inUserCode.getErrorInfo());
}
// re-throw to higher levels so they can put it in correct context.
throw ioe;
}
catch (ClassNotFoundException cnfe)
{
dataIn.clearLimit();
// an exception during the restore of a user column, this doesn't
// make the database corrupt, just that this field is inaccessable
throw StandardException.newException(
SQLState.DATA_STORABLE_READ_MISSING_CLASS,
cnfe, inUserCode.getErrorInfo());
}
catch (LinkageError le)
{
// Some error during the link of a user class
if (inUserCode != null)
{
dataIn.clearLimit();
throw StandardException.newException(
SQLState.DATA_STORABLE_READ_EXCEPTION,
le, inUserCode.getErrorInfo());
}
throw le;
}
}