From faa4e7b2d5e8e156a4fa9788d1c18388f1290cbf Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Thu, 9 Mar 2006 02:00:28 +0000 Subject: [PATCH] apply patches from joniles, 1423965, 1427848 (handling var length columns) git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@37 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../healthmarketscience/jackcess/Column.java | 56 +++++++++++++++++-- .../healthmarketscience/jackcess/Table.java | 17 ++++-- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java index a6c1519..250c3cf 100644 --- a/src/java/com/healthmarketscience/jackcess/Column.java +++ b/src/java/com/healthmarketscience/jackcess/Column.java @@ -273,13 +273,13 @@ public class Column implements Comparable { return null; } else if (_type == DataType.OLE) { if (data.length > 0) { - return getLongValue(data); + return getLongBinaryValue(data); } else { return null; } } else if (_type == DataType.MEMO) { if (data.length > 0) { - return _format.CHARSET.decode(ByteBuffer.wrap(getLongValue(data))).toString(); + return getLongStringValue(data); } else { return null; } @@ -315,16 +315,21 @@ public class Column implements Comparable { throw new IOException("Unrecognized data type: " + _type); } } - + /** * @param lvalDefinition Column value that points to an LVAL record * @return The LVAL data */ @SuppressWarnings("fallthrough") - private byte[] getLongValue(byte[] lvalDefinition) throws IOException { + private byte[] getLongBinaryValue(byte[] lvalDefinition) throws IOException { ByteBuffer def = ByteBuffer.wrap(lvalDefinition); def.order(ByteOrder.LITTLE_ENDIAN); short length = def.getShort(); + // bail out gracefully here as we don't understand the format + if (length < 0) + { + return null; + } byte[] rtn = new byte[length]; short type = def.getShort(); switch (type) { @@ -354,6 +359,49 @@ public class Column implements Comparable { return rtn; } + /** + * @param lvalDefinition Column value that points to an LVAL record + * @return The LVAL data + */ + @SuppressWarnings("fallthrough") + private String getLongStringValue(byte[] lvalDefinition) throws IOException { + ByteBuffer def = ByteBuffer.wrap(lvalDefinition); + def.order(ByteOrder.LITTLE_ENDIAN); + short length = def.getShort(); + byte[] rtn = new byte[length]; + short type = def.getShort(); + String result; + switch (type) { + case LONG_VALUE_TYPE_OTHER_PAGE: + if (lvalDefinition.length != _format.SIZE_LONG_VALUE_DEF) { + throw new IOException("Expected " + _format.SIZE_LONG_VALUE_DEF + + " bytes in long value definition, but found " + lvalDefinition.length); + } + byte rowNum = def.get(); + int pageNum = ByteUtil.get3ByteInt(def, def.position()); + ByteBuffer lvalPage = _pageChannel.createPageBuffer(); + _pageChannel.readPage(lvalPage, pageNum); + short offset = lvalPage.getShort(14 + + rowNum * _format.SIZE_ROW_LOCATION); + lvalPage.position(offset); + lvalPage.get(rtn); + result = _format.CHARSET.decode(ByteBuffer.wrap(rtn)).toString(); + break; + case LONG_VALUE_TYPE_THIS_PAGE: + rtn = new byte[length-2]; + def.position(14); + def.get(rtn); + result = new String(rtn); + break; + case LONG_VALUE_TYPE_OTHER_PAGES: + //XXX + return null; + default: + throw new IOException("Unrecognized long value type: " + type); + } + return result; + } + /** * Write an LVAL column into a ByteBuffer inline (LONG_VALUE_TYPE_THIS_PAGE) * @param value Value of the LVAL column diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java index a9a6944..575d374 100644 --- a/src/java/com/healthmarketscience/jackcess/Table.java +++ b/src/java/com/healthmarketscience/jackcess/Table.java @@ -229,13 +229,20 @@ public class Table { if (column.getType() == DataType.BOOLEAN) { value = new Boolean(!isNull); //Boolean values are stored in the null mask } else { - if (!column.isVariableLength()) { + if (!column.isVariableLength()) + { //Read in fixed length column data - columnData = new byte[column.size()]; + columnData = new byte[column.getLength()]; _buffer.get(columnData); - } else if (!isNull) { - //Refer to already-read-in variable length data - columnData = varColumnData[varColumnDataIndex--]; + } + else + { + if (!isNull) + { + //Refer to already-read-in variable length data + columnData = varColumnData[varColumnDataIndex]; + } + --varColumnDataIndex; } if (!isNull && columnData != null && (columnNames == null || columnNames.contains(column.getName()))) -- 2.39.5