1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
38
39
40 public enum DataType {
41
42
43
44
45
46 BOOLEAN((byte) 0x01, Types.BOOLEAN, 0),
47
48
49
50
51
52
53 BYTE((byte) 0x02, Types.TINYINT, 1),
54
55
56
57
58
59
60 INT((byte) 0x03, Types.SMALLINT, 2),
61
62
63
64
65
66
67 LONG((byte) 0x04, Types.INTEGER, 4),
68
69
70
71
72
73
74
75 MONEY((byte) 0x05, Types.DECIMAL, 8),
76
77
78
79
80
81
82 FLOAT((byte) 0x06, Types.FLOAT, 4),
83
84
85
86
87
88
89 DOUBLE((byte) 0x07, Types.DOUBLE, 8),
90
91
92
93
94
95 SHORT_DATE_TIME((byte) 0x08, Types.TIMESTAMP, 8),
96
97
98
99
100
101 BINARY((byte) 0x09, Types.BINARY, null, true, false, 0, 255, 255, 1),
102
103
104
105
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
112
113
114
115 OLE((byte) 0x0B, Types.LONGVARBINARY, null, true, true, 0, null, 0xFFFFFF,
116 1),
117
118
119
120
121
122 MEMO((byte) 0x0C, Types.LONGVARCHAR, null, true, true, 0, null, 0xFFFFFF,
123 JetFormat.TEXT_FIELD_UNIT_SIZE),
124
125
126
127 UNKNOWN_0D((byte) 0x0D),
128
129
130
131
132
133
134 GUID((byte) 0x0F, null, 16),
135
136
137
138
139
140
141
142 NUMERIC((byte) 0x10, Types.NUMERIC, 17, true, false, 17, 17, 17,
143 true, 0, 0, 28, 1, 18, 28, 1);
144
145
146 private static Map<Integer, DataType> SQL_TYPES = new HashMap<Integer, DataType>();
147
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
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
179 private boolean _variableLength;
180
181 private boolean _longValue;
182
183 private boolean _hasScalePrecision;
184
185 private byte _value;
186
187 private Integer _fixedSize;
188
189 private Integer _minSize;
190
191 private Integer _defaultSize;
192
193 private Integer _maxSize;
194
195 private Integer _sqlType;
196
197 private Integer _minScale;
198
199 private Integer _defaultScale;
200
201 private Integer _maxScale;
202
203 private Integer _minPrecision;
204
205 private Integer _defaultPrecision;
206
207 private Integer _maxPrecision;
208
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
273
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
378 int size = lengthInUnits * rtn.getUnitSize();
379 if(rtn.isVariableLength() && !rtn.isValidSize(size)) {
380
381
382 DataType altRtn = ALT_SQL_TYPES.get(sqlType);
383 if((altRtn != null) &&
384 (altRtn.isLongValue() || altRtn.isValidSize(size))) {
385
386 rtn = altRtn;
387 }
388 }
389
390 return rtn;
391 }
392
393 }