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);
_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);
_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);
}
}
}
if(isAutoNumber()) {
- if((getType() != DataType.LONG) && (getType() != DataType.GUID)) {
+ if(!getType().mayBeAutoNumber()) {
throw new IllegalArgumentException(
"Auto number column must be long integer or guid");
}
(_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);
}
case BINARY:
case UNKNOWN_0D:
+ case UNSUPPORTED_VARLEN:
// should already be "encoded"
break;
default:
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 "
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);
}
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 {
}
}
- /**
- * 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.
*/
}
}
+ 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.
*/
* 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<Integer, DataType> SQL_TYPES = new HashMap<Integer, DataType>();
private static Map<Byte, DataType> DATA_TYPES = new HashMap<Byte, DataType>();
static {
for (DataType type : DataType.values()) {
+ if(type.isUnsupported()) {
+ continue;
+ }
DATA_TYPES.put(type._value, type);
}
}
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));