From 8e21d64746fbf67d98e4ea1360bcd5e5b7e72a6f Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Sun, 12 Nov 2006 19:38:35 +0000 Subject: [PATCH] better import/copy column setup; added ability for users to further customize import/copy behavior through ImportFilter (fix #1593465) git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@133 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../healthmarketscience/jackcess/Column.java | 22 +++-- .../jackcess/DataType.java | 86 ++++++++++++++++--- 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java index a8f2265..2590584 100644 --- a/src/java/com/healthmarketscience/jackcess/Column.java +++ b/src/java/com/healthmarketscience/jackcess/Column.java @@ -192,7 +192,11 @@ public class Column implements Comparable { } public void setSQLType(int type) throws SQLException { - setType(DataType.fromSQLType(type)); + setSQLType(type, 0); + } + + public void setSQLType(int type, int lengthInUnits) throws SQLException { + setType(DataType.fromSQLType(type, lengthInUnits)); } public boolean isCompressedUnicode() { @@ -222,6 +226,13 @@ public class Column implements Comparable { return _columnLength; } + public void setLengthInUnits(short unitLength) { + setLength((short)(getType().getUnitSize() * unitLength)); + } + public short getLengthInUnits() { + return (short)(getLength() / getType().getUnitSize()); + } + public int getVarLenTableIndex() { return _varLenTableIndex; } @@ -251,21 +262,18 @@ public class Column implements Comparable { throw new IllegalArgumentException("invalid fixed length size"); } } else if(!getType().isLongValue()) { - if((getLength() < getType().getMinSize()) || - (getLength() > getType().getMaxSize())) { + if(!getType().isValidSize(getLength())) { throw new IllegalArgumentException("var length out of range"); } } if(getType().getHasScalePrecision()) { - if((getScale() < getType().getMinScale()) || - (getScale() > getType().getMaxScale())) { + if(!getType().isValidScale(getScale())) { throw new IllegalArgumentException( "Scale must be from " + getType().getMinScale() + " to " + getType().getMaxScale() + " inclusive"); } - if((getPrecision() < getType().getMinPrecision()) || - (getPrecision() > getType().getMaxPrecision())) { + if(!getType().isValidPrecision(getPrecision())) { throw new IllegalArgumentException( "Precision must be from " + getType().getMinPrecision() + " to " + getType().getMaxPrecision() + " inclusive"); diff --git a/src/java/com/healthmarketscience/jackcess/DataType.java b/src/java/com/healthmarketscience/jackcess/DataType.java index 889377b..0d4e648 100644 --- a/src/java/com/healthmarketscience/jackcess/DataType.java +++ b/src/java/com/healthmarketscience/jackcess/DataType.java @@ -47,19 +47,24 @@ public enum DataType { FLOAT((byte) 0x06, Types.FLOAT, 4), DOUBLE((byte) 0x07, Types.DOUBLE, 8), SHORT_DATE_TIME((byte) 0x08, Types.TIMESTAMP, 8), - BINARY((byte) 0x09, Types.BINARY, null, true, false, 0, 255, 255), - TEXT((byte) 0x0A, Types.VARCHAR, null, true, false, 0, 50 * 2, - (int)JetFormat.TEXT_FIELD_MAX_LENGTH), - OLE((byte) 0x0B, Types.LONGVARBINARY, null, true, true, 0, null, 0xFFFFFF), - MEMO((byte) 0x0C, Types.LONGVARCHAR, null, true, true, 0, null, 0xFFFFFF), + BINARY((byte) 0x09, Types.BINARY, null, true, false, 0, 255, 255, 1), + TEXT((byte) 0x0A, Types.VARCHAR, null, true, false, 0, + 50 * JetFormat.TEXT_FIELD_UNIT_SIZE, + (int)JetFormat.TEXT_FIELD_MAX_LENGTH, JetFormat.TEXT_FIELD_UNIT_SIZE), + OLE((byte) 0x0B, Types.LONGVARBINARY, null, true, true, 0, null, 0xFFFFFF, + 1), + MEMO((byte) 0x0C, Types.LONGVARCHAR, null, true, true, 0, null, 0xFFFFFF, + JetFormat.TEXT_FIELD_UNIT_SIZE), UNKNOWN_0D((byte) 0x0D), GUID((byte) 0x0F, null, 16), // for some reason numeric is "var len" even though it has a fixed size... NUMERIC((byte) 0x10, Types.NUMERIC, null, true, false, 17, 17, 17, - true, 0, 0, 28, 1, 18, 28); + true, 0, 0, 28, 1, 18, 28, 1); /** Map of SQL types to Access data types */ private static Map SQL_TYPES = new HashMap(); + /** Alternate map of SQL types to Access data types */ + private static Map ALT_SQL_TYPES = new HashMap(); static { for (DataType type : DataType.values()) { if (type._sqlType != null) { @@ -68,12 +73,18 @@ public enum DataType { } SQL_TYPES.put(Types.BIT, BYTE); SQL_TYPES.put(Types.BLOB, OLE); + SQL_TYPES.put(Types.CLOB, MEMO); SQL_TYPES.put(Types.BIGINT, LONG); SQL_TYPES.put(Types.CHAR, TEXT); SQL_TYPES.put(Types.DATE, SHORT_DATE_TIME); SQL_TYPES.put(Types.REAL, DOUBLE); SQL_TYPES.put(Types.TIME, SHORT_DATE_TIME); SQL_TYPES.put(Types.VARBINARY, BINARY); + + // the "alternate" types allow for larger values + ALT_SQL_TYPES.put(Types.VARCHAR, MEMO); + ALT_SQL_TYPES.put(Types.VARBINARY, OLE); + ALT_SQL_TYPES.put(Types.BINARY, OLE); } private static Map DATA_TYPES = new HashMap(); @@ -113,13 +124,15 @@ public enum DataType { private Integer _defaultPrecision; /** max precision value */ private Integer _maxPrecision; + /** the number of bytes per "unit" for this data type */ + private int _unitSize; private DataType(byte value) { this(value, null, null); } private DataType(byte value, Integer sqlType, Integer fixedSize) { - this(value, sqlType, fixedSize, false, false, null, null, null); + this(value, sqlType, fixedSize, false, false, null, null, null, 1); } private DataType(byte value, Integer sqlType, Integer fixedSize, @@ -127,10 +140,11 @@ public enum DataType { boolean longValue, Integer minSize, Integer defaultSize, - Integer maxSize) { + Integer maxSize, + int unitSize) { this(value, sqlType, fixedSize, variableLength, longValue, minSize, defaultSize, maxSize, - false, null, null, null, null, null, null); + false, null, null, null, null, null, null, unitSize); } private DataType(byte value, Integer sqlType, Integer fixedSize, @@ -145,7 +159,8 @@ public enum DataType { Integer maxScale, Integer minPrecision, Integer defaultPrecision, - Integer maxPrecision) { + Integer maxPrecision, + int unitSize) { _value = value; _sqlType = sqlType; _fixedSize = fixedSize; @@ -161,6 +176,7 @@ public enum DataType { _minPrecision = minPrecision; _defaultPrecision = defaultPrecision; _maxPrecision = maxPrecision; + _unitSize = unitSize; } public byte getValue() { @@ -230,6 +246,26 @@ public enum DataType { public int getMaxPrecision() { return _maxPrecision; } + + public int getUnitSize() { + return _unitSize; + } + + public boolean isValidSize(int size) { + return isWithinRange(size, getMinSize(), getMaxSize()); + } + + public boolean isValidScale(int scale) { + return isWithinRange(scale, getMinScale(), getMaxScale()); + } + + public boolean isValidPrecision(int precision) { + return isWithinRange(precision, getMinPrecision(), getMaxPrecision()); + } + + private boolean isWithinRange(int value, int minValue, int maxValue) { + return((value >= minValue) && (value <= maxValue)); + } public static DataType fromByte(byte b) throws IOException { DataType rtn = DATA_TYPES.get(b); @@ -240,13 +276,35 @@ public enum DataType { } } - public static DataType fromSQLType(int sqlType) throws SQLException { + public static DataType fromSQLType(int sqlType) + throws SQLException + { + return fromSQLType(sqlType, 0); + } + + public static DataType fromSQLType(int sqlType, int lengthInUnits) + throws SQLException + { DataType rtn = SQL_TYPES.get(sqlType); - if (rtn != null) { - return rtn; - } else { + if(rtn == null) { throw new SQLException("Unsupported SQL type: " + sqlType); } + + if(rtn.isVariableLength()) { + // make sure size is reasonable + if(lengthInUnits > (rtn.getMaxSize() * rtn.getUnitSize())) { + // try alternate types + DataType altRtn = ALT_SQL_TYPES.get(sqlType); + if(altRtn != null) { + if(lengthInUnits <= (altRtn.getMaxSize() * altRtn.getUnitSize())) { + // use alternate type + rtn = altRtn; + } + } + } + } + + return rtn; } } -- 2.39.5