{
ErrorObjectInput inUserCode = null;
// Reads in this routine are always against the raw data in the
// pageData array, thus it can assume array access to page data array.
ArrayInputStream lrdi = rawDataIn;
try
{
if (SanityManager.DEBUG)
{
if (colid >= row.length)
SanityManager.THROWASSERT(
"colid = " + colid +
";row length = " + row.length);
// currently this routine will not work on long rows.
if (recordHeader.getFirstField() != 0)
{
SanityManager.THROWASSERT(
"recordHeader.getFirstField() = " +
recordHeader.getFirstField());
}
}
Object column = row[colid];
// if the column id exists on this page.
if (colid <= (recordHeader.getNumberFields() - 1))
{
// skip the fields before colid, the column in question
// existent on this page.
for (int columnId = colid; columnId > 0; columnId--)
{
offset_to_field_data +=
StoredFieldHeader.readTotalFieldLength(
pageData, offset_to_field_data);
}
// read the field header
// read the status byte.
int fieldStatus =
StoredFieldHeader.readStatus(
pageData, offset_to_field_data);
// read the field data length, and position on 1st byte of data.
int fieldDataLength =
StoredFieldHeader.readFieldLengthAndSetStreamPosition(
pageData,
offset_to_field_data +
StoredFieldHeader.STORED_FIELD_HEADER_STATUS_SIZE,
fieldStatus,
slotFieldSize,
lrdi);
if (SanityManager.DEBUG)
{
SanityManager.ASSERT(
!StoredFieldHeader.isExtensible(fieldStatus),
"extensible fields not supported yet");
}
// SRW-DJD code assumes non-extensible case ...
if (!StoredFieldHeader.isNonexistent(fieldStatus))
{
boolean isOverflow =
StoredFieldHeader.isOverflow(fieldStatus);
OverflowInputStream overflowIn = null;
if (isOverflow)
{
// A fetched long column is returned as a stream
long overflowPage =
CompressedNumber.readLong((InputStream) lrdi);
int overflowId =
CompressedNumber.readInt((InputStream) lrdi);
// 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 Storable columns
if (column instanceof DataValueDescriptor)
{
DataValueDescriptor sColumn =
(DataValueDescriptor) column;
// is the column null ?
if (StoredFieldHeader.isNull(fieldStatus))
{
sColumn.restoreToNull();
}
else
{
// set the limit for the user read
if (!isOverflow)
{
// normal, non-overflow column case.
lrdi.setLimit(fieldDataLength);
inUserCode = lrdi;
sColumn.readExternalFromArray(lrdi);
inUserCode = null;
int unread = lrdi.clearLimit();
if (unread != 0)
lrdi.skipBytes(unread);
}
else
{
// fetched column is a Storable long column.
FormatIdInputStream newIn =
new FormatIdInputStream(overflowIn);
if ((sColumn instanceof StreamStorable))
{
((StreamStorable)sColumn).setStream(newIn);
}
else
{
inUserCode = newIn;
sColumn.readExternal(newIn);
inUserCode = null;
}
}
}
}
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(colid));
}
// 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.
lrdi.setLimit(fieldDataLength);
inUserCode = lrdi;
// RESOLVE (no non-storables?)
row[colid] = (Object) lrdi.readObject();
inUserCode = null;
int unread = lrdi.clearLimit();
if (unread != 0)
lrdi.skipBytes(unread);
}
}
else
{
// column does not exist in the row, return null.
// field 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[colid] = null;
}
}
}
else
{
// field does not exist on this page.
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[colid] = null;
}
}
}
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)
{
lrdi.clearLimit();
if (ioe instanceof EOFException)
{
if (SanityManager.DEBUG)
{
SanityManager.DEBUG_PRINT("DEBUG_TRACE",
"StoredPage.readOneColumnFromPage - EOF while restoring record: " +
recordHeader +
"Page dump = " + this);
SanityManager.showTrace(ioe);
}
// 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)
{
lrdi.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)
{
lrdi.clearLimit();
throw StandardException.newException(
SQLState.DATA_STORABLE_READ_EXCEPTION,
le, inUserCode.getErrorInfo());
}