From deb9e04ba9908ff5a4138bd7f539d65e946fdf31 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Mon, 11 Jul 2011 02:39:55 +0000 Subject: [PATCH] Enable basic handling of unsupported data types as binary content. git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@567 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 3 + .../healthmarketscience/jackcess/Column.java | 99 ++++++++++++++----- .../jackcess/DataType.java | 24 ++++- 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a030d07..3f86887 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -12,6 +12,9 @@ Add the Joiner utility and some new methods to IndexCursor to make it easier to join tables using pre-defined (index backed) relationships. + + Enable basic handling of unsupported data types as binary content. + diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java index 9636771..b4afdbb 100644 --- a/src/java/com/healthmarketscience/jackcess/Column.java +++ b/src/java/com/healthmarketscience/jackcess/Column.java @@ -217,9 +217,25 @@ public class Column implements Comparable { if (LOG.isDebugEnabled()) { LOG.debug("Column def block:\n" + ByteUtil.toHexString(buffer, offset, 25)); } - setType(DataType.fromByte(buffer.get(offset + getFormat().OFFSET_COLUMN_TYPE))); + + byte colType = buffer.get(offset + getFormat().OFFSET_COLUMN_TYPE); _columnNumber = buffer.getShort(offset + getFormat().OFFSET_COLUMN_NUMBER); _columnLength = buffer.getShort(offset + getFormat().OFFSET_COLUMN_LENGTH); + + byte flags = buffer.get(offset + getFormat().OFFSET_COLUMN_FLAGS); + _variableLength = ((flags & FIXED_LEN_FLAG_MASK) == 0); + _autoNumber = ((flags & (AUTO_NUMBER_FLAG_MASK | AUTO_NUMBER_GUID_FLAG_MASK)) != 0); + + try { + _type = DataType.fromByte(colType); + } catch(IOException e) { + LOG.warn("Unsupported column type " + colType); + _type = (_variableLength ? DataType.UNSUPPORTED_VARLEN : + DataType.UNSUPPORTED_FIXEDLEN); + // slight hack, stash the original type in the _scale + _scale = colType; + } + if (_type.getHasScalePrecision()) { _precision = buffer.get(offset + getFormat().OFFSET_COLUMN_PRECISION); _scale = buffer.get(offset + getFormat().OFFSET_COLUMN_SCALE); @@ -232,11 +248,8 @@ public class Column implements Comparable { _textCodePage = buffer.getShort(offset + cpOffset); } } - byte flags = buffer.get(offset + getFormat().OFFSET_COLUMN_FLAGS); - _variableLength = ((flags & FIXED_LEN_FLAG_MASK) == 0); - _autoNumber = ((flags & (AUTO_NUMBER_FLAG_MASK | AUTO_NUMBER_GUID_FLAG_MASK)) != 0); setAutoNumberGenerator(); - + _compressedUnicode = ((buffer.get(offset + getFormat().OFFSET_COLUMN_COMPRESSED_UNICODE) & 1) == 1); @@ -436,7 +449,8 @@ public class Column implements Comparable { _autoNumberGenerator = new GuidAutoNumberGenerator(); break; default: - throw new RuntimeException("Unexpected autoNumber column type " + _type); + LOG.warn("Unknown auto number column type " + _type); + _autoNumberGenerator = new UnsupportedAutoNumberGenerator(_type); } } @@ -503,7 +517,7 @@ public class Column implements Comparable { } if(isAutoNumber()) { - if((getType() != DataType.LONG) && (getType() != DataType.GUID)) { + if(!getType().mayBeAutoNumber()) { throw new IllegalArgumentException( "Auto number column must be long integer or guid"); } @@ -573,6 +587,8 @@ public class Column implements Comparable { (_type == DataType.UNKNOWN_11)) { // treat like "binary" data return data; + } else if(_type.isUnsupported()) { + return rawDataWrapper(data); } else { throw new IOException("Unrecognized data type: " + _type); } @@ -1164,6 +1180,7 @@ public class Column implements Comparable { case BINARY: case UNKNOWN_0D: + case UNSUPPORTED_VARLEN: // should already be "encoded" break; default: @@ -1255,6 +1272,7 @@ public class Column implements Comparable { case BINARY: case UNKNOWN_0D: case UNKNOWN_11: + case UNSUPPORTED_FIXEDLEN: byte[] bytes = toByteArray(obj); if(bytes.length != getLength()) { throw new IOException("Invalid fixed size binary data, size " @@ -1420,11 +1438,30 @@ public class Column implements Comparable { return true; } + /** + * Constructs a byte containing the flags for this column. + */ + private byte getColumnBitFlags() { + byte flags = Column.UNKNOWN_FLAG_MASK; + if(!isVariableLength()) { + flags |= Column.FIXED_LEN_FLAG_MASK; + } + if(isAutoNumber()) { + flags |= getAutoNumberGenerator().getColumnFlags(); + } + return flags; + } + @Override public String toString() { StringBuilder rtn = new StringBuilder(); rtn.append("\tName: (" + _table.getName() + ") " + _name); - rtn.append("\n\tType: 0x" + Integer.toHexString(_type.getValue()) + + byte typeValue = _type.getValue(); + if(_type.isUnsupported()) { + // slight hack, we stashed the real type in the _scale + typeValue = _scale; + } + rtn.append("\n\tType: 0x" + Integer.toHexString(typeValue) + " (" + _type + ")"); rtn.append("\n\tNumber: " + _columnNumber); rtn.append("\n\tLength: " + _columnLength); @@ -1709,7 +1746,7 @@ public class Column implements Comparable { } buffer.putShort((short) 0); //Unknown } - buffer.put(getColumnBitFlags(col)); // misc col flags + buffer.put(col.getColumnBitFlags()); // misc col flags if (col.isCompressedUnicode()) { //Compressed buffer.put((byte) 1); } else { @@ -1739,20 +1776,6 @@ public class Column implements Comparable { } } - /** - * Constructs a byte containing the flags for the given column. - */ - private static byte getColumnBitFlags(Column col) { - byte flags = Column.UNKNOWN_FLAG_MASK; - if(!col.isVariableLength()) { - flags |= Column.FIXED_LEN_FLAG_MASK; - } - if(col.isAutoNumber()) { - flags |= col.getAutoNumberGenerator().getColumnFlags(); - } - return flags; - } - /** * Reads the sort order info from the given buffer from the given position. */ @@ -1940,6 +1963,36 @@ public class Column implements Comparable { } } + private final class UnsupportedAutoNumberGenerator extends AutoNumberGenerator + { + private final DataType _genType; + + private UnsupportedAutoNumberGenerator(DataType genType) { + _genType = genType; + } + + @Override + public Object getLast() { + return null; + } + + @Override + public Object getNext() { + throw new UnsupportedOperationException(); + } + + @Override + public int getColumnFlags() { + throw new UnsupportedOperationException(); + } + + @Override + public DataType getType() { + return _genType; + } + } + + /** * Information about the sort order (collation) for a textual column. */ diff --git a/src/java/com/healthmarketscience/jackcess/DataType.java b/src/java/com/healthmarketscience/jackcess/DataType.java index 079c1e7..bc5e13d 100644 --- a/src/java/com/healthmarketscience/jackcess/DataType.java +++ b/src/java/com/healthmarketscience/jackcess/DataType.java @@ -146,7 +146,18 @@ public enum DataType { * Unknown data (seems to be an alternative OLE type, used by * MSysAccessObjects table). Handled like a fixed length BINARY/OLE. */ - UNKNOWN_11((byte) 0x11, null, 3992); + UNKNOWN_11((byte) 0x11, null, 3992), + /** + * Dummy type for a fixed length type which is not currently supported. + * Handled like a fixed length BINARY. + */ + UNSUPPORTED_FIXEDLEN((byte) 0xFE, null, null), + /** + * Placeholder type for a variable length type which is not currently supported. + * Handled like BINARY. + */ + UNSUPPORTED_VARLEN((byte) 0xFF, null, null, true, false, 0, null, 0x3FFFFFFF, + 1); /** Map of SQL types to Access data types */ private static Map SQL_TYPES = new HashMap(); @@ -177,6 +188,9 @@ public enum DataType { private static Map DATA_TYPES = new HashMap(); static { for (DataType type : DataType.values()) { + if(type.isUnsupported()) { + continue; + } DATA_TYPES.put(type._value, type); } } @@ -395,6 +409,14 @@ public enum DataType { return ((this == TEXT) || (this == MEMO)); } + public boolean mayBeAutoNumber() { + return((this == LONG) || (this == GUID)); + } + + public boolean isUnsupported() { + return((this == UNSUPPORTED_FIXEDLEN) || (this == UNSUPPORTED_VARLEN)); + } + private static int toValidRange(int value, int minValue, int maxValue) { return((value > maxValue) ? maxValue : ((value < minValue) ? minValue : value)); -- 2.39.5