View Javadoc

1   /*
2   Copyright (c) 2005 Health Market Science, Inc.
3   
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8   
9   This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Lesser General Public License for more details.
13  
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17  USA
18  
19  You can contact Health Market Science at info@healthmarketscience.com
20  or at the following address:
21  
22  Health Market Science
23  2700 Horizon Drive
24  Suite 200
25  King of Prussia, PA 19406
26  */
27  
28  package com.healthmarketscience.jackcess;
29  
30  import java.io.IOException;
31  import java.sql.SQLException;
32  import java.sql.Types;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  /**
37   * Access data type
38   * @author Tim McCune
39   */
40  public enum DataType {
41  
42    /**
43     * Corresponds to a java Boolean.  Accepts Boolean or {@code null} (which is
44     * considered {@code false}).  Equivalent to SQL {@link Types#BOOLEAN}.
45     */
46    BOOLEAN((byte) 0x01, Types.BOOLEAN, 0),
47    /**
48     * Corresponds to a java Byte.  Accepts any Number (using
49     * {@link Number#byteValue}), Boolean as 1 or 0, any Object converted to a
50     * String and parsed as Double, or {@code null}.  Equivalent to SQL
51     * {@link Types#TINYINT}, {@link Types#BIT}.
52     */
53    BYTE((byte) 0x02, Types.TINYINT, 1),
54    /**
55     * Corresponds to a java Short.  Accepts any Number (using
56     * {@link Number#shortValue}), Boolean as 1 or 0, any Object converted to a
57     * String and parsed as Double, or {@code null}.  Equivalent to SQL
58     * {@link Types#SMALLINT}.
59     */
60    INT((byte) 0x03, Types.SMALLINT, 2),
61    /**
62     * Corresponds to a java Integer.  Accepts any Number (using
63     * {@link Number#intValue}), Boolean as 1 or 0, any Object converted to a
64     * String and parsed as Double, or {@code null}.  Equivalent to SQL
65     * {@link Types#INTEGER}, {@link Types#BIGINT}.
66     */
67    LONG((byte) 0x04, Types.INTEGER, 4),
68    /**
69     * Corresponds to a java BigDecimal with at most 4 decimal places.  Accepts
70     * any Number (using {@link Number#doubleValue}), a BigInteger, a BigDecimal
71     * (with at most 4 decimal places), Boolean as 1 or 0, any Object converted
72     * to a String and parsed as BigDecimal, or {@code null}.  Equivalent to SQL
73     * {@link Types#DECIMAL}.
74     */
75    MONEY((byte) 0x05, Types.DECIMAL, 8),
76    /**
77     * Corresponds to a java Float.  Accepts any Number (using
78     * {@link Number#floatValue}), Boolean as 1 or 0, any Object converted to a
79     * String and parsed as Double, or {@code null}.  Equivalent to SQL
80     * {@link Types#FLOAT}.
81     */
82    FLOAT((byte) 0x06, Types.FLOAT, 4),
83    /**
84     * Corresponds to a java Double.  Accepts any Number (using
85     * {@link Number#doubleValue}), Boolean as 1 or 0, any Object converted to a
86     * String and parsed as Double, or {@code null}.  Equivalent to SQL
87     * {@link Types#DOUBLE}, {@link Types#REAL}.
88     */
89    DOUBLE((byte) 0x07, Types.DOUBLE, 8),
90    /**
91     * Corresponds to a java Date.  Accepts a Date, any Number (using
92     * {@link Number#longValue}), or {@code null}.  Equivalent to SQL
93     * {@link Types#TIMESTAMP}, {@link Types#DATE}, {@link Types#TIME}.
94     */
95    SHORT_DATE_TIME((byte) 0x08, Types.TIMESTAMP, 8),
96    /**
97     * Corresponds to a java {@code byte[]} of max length 255 bytes.  Accepts a
98     * {@code byte[]}, or {@code null}.  Equivalent to SQL {@link Types#BINARY},
99     * {@link Types#VARBINARY}.
100    */
101   BINARY((byte) 0x09, Types.BINARY, null, true, false, 0, 255, 255, 1),
102   /**
103    * Corresponds to a java String of max length 255 chars.  Accepts any
104    * CharSequence, any Object converted to a String , or {@code null}.
105    * Equivalent to SQL {@link Types#VARCHAR}, {@link Types#CHAR}.
106    */
107   TEXT((byte) 0x0A, Types.VARCHAR, null, true, false, 0,
108        50 * JetFormat.TEXT_FIELD_UNIT_SIZE,
109        (int)JetFormat.TEXT_FIELD_MAX_LENGTH, JetFormat.TEXT_FIELD_UNIT_SIZE),
110   /**
111    * Corresponds to a java {@code byte[]} of max length 16777215 bytes.
112    * Accepts a {@code byte[]}, or {@code null}.  Equivalent to SQL
113    * {@link Types#LONGVARBINARY}, {@link Types#BLOB}.
114    */
115   OLE((byte) 0x0B, Types.LONGVARBINARY, null, true, true, 0, null, 0xFFFFFF,
116       1),
117   /**
118    * Corresponds to a java String of max length 8388607 chars.  Accepts any
119    * CharSequence, any Object converted to a String , or {@code null}.
120    * Equivalent to SQL {@link Types#LONGVARCHAR}, {@link Types#CLOB}.
121    */
122   MEMO((byte) 0x0C, Types.LONGVARCHAR, null, true, true, 0, null, 0xFFFFFF,
123        JetFormat.TEXT_FIELD_UNIT_SIZE),
124   /**
125    * Unknown data.  Accepts {@code null}.
126    */
127   UNKNOWN_0D((byte) 0x0D),
128   /**
129    * Corresponds to a java String with the pattern
130    * <code>"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"</code>.  Accepts any
131    * Object converted to a String matching this pattern (surrounding "{}" are
132    * optional, so {@link java.util.UUID}s are supported), or {@code null}.
133    */
134   GUID((byte) 0x0F, null, 16),
135   /**
136    * Corresponds to a java BigDecimal.  Accepts any Number (using
137    * {@link Number#doubleValue}), a BigInteger, a BigDecimal, Boolean as 1 or
138    * 0, any Object converted to a String and parsed as BigDecimal, or
139    * {@code null}.  Equivalent to SQL {@link Types#NUMERIC}.
140    */
141   // for some reason numeric is "var len" even though it has a fixed size...
142   NUMERIC((byte) 0x10, Types.NUMERIC, 17, true, false, 17, 17, 17,
143           true, 0, 0, 28, 1, 18, 28, 1);
144 
145   /** Map of SQL types to Access data types */
146   private static Map<Integer, DataType> SQL_TYPES = new HashMap<Integer, DataType>();
147   /** Alternate map of SQL types to Access data types */
148   private static Map<Integer, DataType> ALT_SQL_TYPES = new HashMap<Integer, DataType>();
149   static {
150     for (DataType type : DataType.values()) {
151       if (type._sqlType != null) {
152         SQL_TYPES.put(type._sqlType, type);
153       }
154     }
155     SQL_TYPES.put(Types.BIT, BYTE);
156     SQL_TYPES.put(Types.BLOB, OLE);
157     SQL_TYPES.put(Types.CLOB, MEMO);
158     SQL_TYPES.put(Types.BIGINT, LONG);
159     SQL_TYPES.put(Types.CHAR, TEXT);
160     SQL_TYPES.put(Types.DATE, SHORT_DATE_TIME);
161     SQL_TYPES.put(Types.REAL, DOUBLE);
162     SQL_TYPES.put(Types.TIME, SHORT_DATE_TIME);
163     SQL_TYPES.put(Types.VARBINARY, BINARY);
164 
165     // the "alternate" types allow for larger values
166     ALT_SQL_TYPES.put(Types.VARCHAR, MEMO);
167     ALT_SQL_TYPES.put(Types.VARBINARY, OLE);
168     ALT_SQL_TYPES.put(Types.BINARY, OLE);
169   }
170   
171   private static Map<Byte, DataType> DATA_TYPES = new HashMap<Byte, DataType>();
172   static {
173     for (DataType type : DataType.values()) {
174       DATA_TYPES.put(type._value, type);
175     }
176   }
177 
178   /** is this a variable length field */
179   private boolean _variableLength;
180   /** is this a long value field */
181   private boolean _longValue;
182   /** does this field have scale/precision */
183   private boolean _hasScalePrecision;
184   /** Internal Access value */
185   private byte _value;
186   /** Size in bytes of fixed length columns */
187   private Integer _fixedSize;
188   /** min in bytes size for var length columns */
189   private Integer _minSize;
190   /** default size in bytes for var length columns */
191   private Integer _defaultSize;
192   /** Max size in bytes for var length columns */
193   private Integer _maxSize;
194   /** SQL type equivalent, or null if none defined */
195   private Integer _sqlType;
196   /** min scale value */
197   private Integer _minScale;
198   /** the default scale value */
199   private Integer _defaultScale;
200   /** max scale value */
201   private Integer _maxScale;
202   /** min precision value */
203   private Integer _minPrecision;
204   /** the default precision value */
205   private Integer _defaultPrecision;
206   /** max precision value */
207   private Integer _maxPrecision;
208   /** the number of bytes per "unit" for this data type */
209   private int _unitSize;
210   
211   private DataType(byte value) {
212     this(value, null, null);
213   }
214   
215   private DataType(byte value, Integer sqlType, Integer fixedSize) {
216     this(value, sqlType, fixedSize, false, false, null, null, null, 1);
217   }
218 
219   private DataType(byte value, Integer sqlType, Integer fixedSize,
220                    boolean variableLength,
221                    boolean longValue,
222                    Integer minSize,
223                    Integer defaultSize,
224                    Integer maxSize,
225                    int unitSize) {
226     this(value, sqlType, fixedSize, variableLength, longValue,
227          minSize, defaultSize, maxSize,
228          false, null, null, null, null, null, null, unitSize);
229   }
230   
231   private DataType(byte value, Integer sqlType, Integer fixedSize,
232                    boolean variableLength,
233                    boolean longValue,
234                    Integer minSize,
235                    Integer defaultSize,
236                    Integer maxSize,
237                    boolean hasScalePrecision,
238                    Integer minScale,
239                    Integer defaultScale,
240                    Integer maxScale,
241                    Integer minPrecision,
242                    Integer defaultPrecision,
243                    Integer maxPrecision,
244                    int unitSize) {
245     _value = value;
246     _sqlType = sqlType;
247     _fixedSize = fixedSize;
248     _variableLength = variableLength;
249     _longValue = longValue;
250     _minSize = minSize;
251     _defaultSize = defaultSize;
252     _maxSize = maxSize;
253     _hasScalePrecision = hasScalePrecision;
254     _minScale = minScale;
255     _defaultScale = defaultScale;
256     _maxScale = maxScale;
257     _minPrecision = minPrecision;
258     _defaultPrecision = defaultPrecision;
259     _maxPrecision = maxPrecision;
260     _unitSize = unitSize;
261   }
262   
263   public byte getValue() {
264     return _value;
265   }
266   
267   public boolean isVariableLength() {
268     return _variableLength;
269   }
270 
271   public boolean isTrueVariableLength() {
272     // some "var len" fields do not really have a variable length,
273     // e.g. NUMERIC
274     return (isVariableLength() && (getMinSize() != getMaxSize()));
275   }
276   
277   public boolean isLongValue() {
278     return _longValue;
279   }
280 
281   public boolean getHasScalePrecision() {
282     return _hasScalePrecision;
283   }
284   
285   public int getFixedSize() {
286     if(_fixedSize != null) {
287       return _fixedSize;
288     }
289     throw new IllegalArgumentException("FIX ME");
290   }
291 
292   public int getMinSize() {
293     return _minSize;
294   }
295 
296   public int getDefaultSize() {
297     return _defaultSize;
298   }
299 
300   public int getMaxSize() {
301     return _maxSize;
302   }
303   
304   public int getSQLType() throws SQLException {
305     if (_sqlType != null) {
306       return _sqlType;
307     }
308     throw new SQLException("Unsupported data type: " + toString());
309   }
310 
311   public int getMinScale() {
312     return _minScale;
313   }
314 
315   public int getDefaultScale() {
316     return _defaultScale;
317   }
318   
319   public int getMaxScale() {
320     return _maxScale;
321   }
322   
323   public int getMinPrecision() {
324     return _minPrecision;
325   }
326   
327   public int getDefaultPrecision() {
328     return _defaultPrecision;
329   }
330   
331   public int getMaxPrecision() {
332     return _maxPrecision;
333   }
334 
335   public int getUnitSize() {
336     return _unitSize;
337   }
338 
339   public boolean isValidSize(int size) {
340     return isWithinRange(size, getMinSize(), getMaxSize());
341   }
342 
343   public boolean isValidScale(int scale) {
344     return isWithinRange(scale, getMinScale(), getMaxScale());
345   }
346 
347   public boolean isValidPrecision(int precision) {
348     return isWithinRange(precision, getMinPrecision(), getMaxPrecision());
349   }
350 
351   private boolean isWithinRange(int value, int minValue, int maxValue) {
352     return((value >= minValue) && (value <= maxValue));
353   }
354   
355   public static DataType fromByte(byte b) throws IOException {
356     DataType rtn = DATA_TYPES.get(b);
357     if (rtn != null) {
358       return rtn;
359     }
360     throw new IOException("Unrecognized data type: " + b);
361   }
362   
363   public static DataType fromSQLType(int sqlType)
364   throws SQLException
365   {
366     return fromSQLType(sqlType, 0);
367   }
368   
369   public static DataType fromSQLType(int sqlType, int lengthInUnits)
370   throws SQLException
371   {
372     DataType rtn = SQL_TYPES.get(sqlType);
373     if(rtn == null) {
374       throw new SQLException("Unsupported SQL type: " + sqlType);
375     }
376 
377     // make sure size is reasonable
378     int size = lengthInUnits * rtn.getUnitSize();
379     if(rtn.isVariableLength() && !rtn.isValidSize(size)) {
380       // try alternate type.  we always accept alternate "long value" types
381       // regardless of the given lengthInUnits
382       DataType altRtn = ALT_SQL_TYPES.get(sqlType);
383       if((altRtn != null) &&
384          (altRtn.isLongValue() || altRtn.isValidSize(size))) {
385         // use alternate type
386         rtn = altRtn;
387       }
388     }
389       
390     return rtn;
391   }
392 
393 }