1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess.impl;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.nio.channels.FileChannel;
22 import java.nio.charset.Charset;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Collections;
25 import java.util.EnumSet;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.Set;
29
30 import com.healthmarketscience.jackcess.DataType;
31 import com.healthmarketscience.jackcess.Database;
32
33
34
35
36
37 public abstract class JetFormat {
38
39
40 public static final int MAX_RECORD_SIZE = 1900;
41
42
43 public static final short TEXT_FIELD_UNIT_SIZE = 2;
44
45 public static final short TEXT_FIELD_MAX_LENGTH = 255 * TEXT_FIELD_UNIT_SIZE;
46
47 public enum CodecType {
48 NONE, JET, MSISAM, OFFICE;
49 }
50
51
52
53 private static final int OFFSET_VERSION = 20;
54
55 private static final byte CODE_VERSION_3 = 0x0;
56
57 private static final byte CODE_VERSION_4 = 0x1;
58
59 private static final byte CODE_VERSION_12 = 0x2;
60
61 private static final byte CODE_VERSION_14 = 0x3;
62
63 private static final byte CODE_VERSION_16 = 0x5;
64
65 private static final byte CODE_VERSION_17 = 0x6;
66
67
68 public static final int OFFSET_ENGINE_NAME = 0x4;
69
70 public static final int LENGTH_ENGINE_NAME = 0xF;
71
72 private static final int HEADER_LENGTH = 21;
73
74 private final static byte[] MSISAM_ENGINE = new byte[] {
75 'M', 'S', 'I', 'S', 'A', 'M', ' ', 'D', 'a', 't', 'a', 'b', 'a', 's', 'e'
76 };
77
78
79 private static final byte[] BASE_HEADER_MASK = new byte[]{
80 (byte)0xB5, (byte)0x6F, (byte)0x03, (byte)0x62, (byte)0x61, (byte)0x08,
81 (byte)0xC2, (byte)0x55, (byte)0xEB, (byte)0xA9, (byte)0x67, (byte)0x72,
82 (byte)0x43, (byte)0x3F, (byte)0x00, (byte)0x9C, (byte)0x7A, (byte)0x9F,
83 (byte)0x90, (byte)0xFF, (byte)0x80, (byte)0x9A, (byte)0x31, (byte)0xC5,
84 (byte)0x79, (byte)0xBA, (byte)0xED, (byte)0x30, (byte)0xBC, (byte)0xDF,
85 (byte)0xCC, (byte)0x9D, (byte)0x63, (byte)0xD9, (byte)0xE4, (byte)0xC3,
86 (byte)0x7B, (byte)0x42, (byte)0xFB, (byte)0x8A, (byte)0xBC, (byte)0x4E,
87 (byte)0x86, (byte)0xFB, (byte)0xEC, (byte)0x37, (byte)0x5D, (byte)0x44,
88 (byte)0x9C, (byte)0xFA, (byte)0xC6, (byte)0x5E, (byte)0x28, (byte)0xE6,
89 (byte)0x13, (byte)0xB6, (byte)0x8A, (byte)0x60, (byte)0x54, (byte)0x94,
90 (byte)0x7B, (byte)0x36, (byte)0xF5, (byte)0x72, (byte)0xDF, (byte)0xB1,
91 (byte)0x77, (byte)0xF4, (byte)0x13, (byte)0x43, (byte)0xCF, (byte)0xAF,
92 (byte)0xB1, (byte)0x33, (byte)0x34, (byte)0x61, (byte)0x79, (byte)0x5B,
93 (byte)0x92, (byte)0xB5, (byte)0x7C, (byte)0x2A, (byte)0x05, (byte)0xF1,
94 (byte)0x7C, (byte)0x99, (byte)0x01, (byte)0x1B, (byte)0x98, (byte)0xFD,
95 (byte)0x12, (byte)0x4F, (byte)0x4A, (byte)0x94, (byte)0x6C, (byte)0x3E,
96 (byte)0x60, (byte)0x26, (byte)0x5F, (byte)0x95, (byte)0xF8, (byte)0xD0,
97 (byte)0x89, (byte)0x24, (byte)0x85, (byte)0x67, (byte)0xC6, (byte)0x1F,
98 (byte)0x27, (byte)0x44, (byte)0xD2, (byte)0xEE, (byte)0xCF, (byte)0x65,
99 (byte)0xED, (byte)0xFF, (byte)0x07, (byte)0xC7, (byte)0x46, (byte)0xA1,
100 (byte)0x78, (byte)0x16, (byte)0x0C, (byte)0xED, (byte)0xE9, (byte)0x2D,
101 (byte)0x62, (byte)0xD4};
102
103
104
105 private static final String ACCESS_VERSION_2000 = "08.50";
106
107
108 private static final String ACCESS_VERSION_2003 = "09.50";
109
110
111 static final byte[][] PROPERTY_MAP_TYPES = {
112 new byte[]{'M', 'R', '2', '\0'},
113 new byte[]{'K', 'K', 'D', '\0'}};
114
115
116 private static final class PossibleFileFormats {
117 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_3 =
118 Collections.singletonMap((String)null, Database.FileFormat.V1997);
119
120 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_4 =
121 new HashMap<String,Database.FileFormat>();
122
123 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_12 =
124 Collections.singletonMap((String)null, Database.FileFormat.V2007);
125
126 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_14 =
127 Collections.singletonMap((String)null, Database.FileFormat.V2010);
128
129 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_16 =
130 Collections.singletonMap((String)null, Database.FileFormat.V2016);
131
132 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_17 =
133 Collections.singletonMap((String)null, Database.FileFormat.V2019);
134
135 private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_MSISAM =
136 Collections.singletonMap((String)null, Database.FileFormat.MSISAM);
137
138 static {
139 POSSIBLE_VERSION_4.put(ACCESS_VERSION_2000, Database.FileFormat.V2000);
140 POSSIBLE_VERSION_4.put(ACCESS_VERSION_2003, Database.FileFormat.V2003);
141 POSSIBLE_VERSION_4.put(null, Database.FileFormat.GENERIC_JET4);
142 }
143 }
144
145
146 private static final Set<DataType> V14_CALC_TYPES =
147 EnumSet.of(DataType.BOOLEAN, DataType.BYTE, DataType.INT, DataType.LONG,
148 DataType.FLOAT, DataType.DOUBLE, DataType.GUID,
149 DataType.SHORT_DATE_TIME, DataType.MONEY, DataType.NUMERIC,
150 DataType.TEXT, DataType.MEMO);
151
152
153 private static final Set<DataType> V16_CALC_TYPES = EnumSet.of(DataType.BIG_INT);
154 static {
155 V16_CALC_TYPES.addAll(V14_CALC_TYPES);
156 }
157
158 private static final Set<DataType> V16_UNSUPP_TYPES =
159 EnumSet.of(DataType.EXT_DATE_TIME);
160 private static final Set<DataType> V12_UNSUPP_TYPES =
161 EnumSet.of(DataType.BIG_INT);
162 private static final Set<DataType> V3_UNSUPP_TYPES =
163 EnumSet.of(DataType.COMPLEX_TYPE);
164
165 static {
166 V12_UNSUPP_TYPES.addAll(V16_UNSUPP_TYPES);
167 V3_UNSUPP_TYPES.addAll(V12_UNSUPP_TYPES);
168 }
169
170
171 public static final JetFormat VERSION_3 = new Jet3Format();
172
173 public static final JetFormat VERSION_4 = new Jet4Format();
174
175 public static final JetFormat VERSION_MSISAM = new MSISAMFormat();
176
177 public static final JetFormat VERSION_12 = new Jet12Format();
178
179 public static final JetFormat VERSION_14 = new Jet14Format();
180
181 public static final JetFormat VERSION_16 = new Jet16Format();
182
183 public static final JetFormat VERSION_17 = new Jet17Format();
184
185
186
187
188
189
190 private final String _name;
191
192
193 public final boolean READ_ONLY;
194
195
196 public final boolean INDEXES_SUPPORTED;
197
198
199 public final CodecType CODEC_TYPE;
200
201
202 public final int PAGE_SIZE;
203 public final long MAX_DATABASE_SIZE;
204
205 public final int MAX_ROW_SIZE;
206 public final int DATA_PAGE_INITIAL_FREE_SPACE;
207
208 public final int OFFSET_MASKED_HEADER;
209 public final byte[] HEADER_MASK;
210 public final int OFFSET_HEADER_DATE;
211 public final int OFFSET_PASSWORD;
212 public final int SIZE_PASSWORD;
213 public final int OFFSET_SORT_ORDER;
214 public final int SIZE_SORT_ORDER;
215 public final int OFFSET_CODE_PAGE;
216 public final int OFFSET_ENCODING_KEY;
217 public final int OFFSET_NEXT_TABLE_DEF_PAGE;
218 public final int OFFSET_NUM_ROWS;
219 public final int OFFSET_NEXT_AUTO_NUMBER;
220 public final int OFFSET_NEXT_COMPLEX_AUTO_NUMBER;
221 public final int OFFSET_TABLE_TYPE;
222 public final int OFFSET_MAX_COLS;
223 public final int OFFSET_NUM_VAR_COLS;
224 public final int OFFSET_NUM_COLS;
225 public final int OFFSET_NUM_INDEX_SLOTS;
226 public final int OFFSET_NUM_INDEXES;
227 public final int OFFSET_OWNED_PAGES;
228 public final int OFFSET_FREE_SPACE_PAGES;
229 public final int OFFSET_INDEX_DEF_BLOCK;
230
231 public final int SIZE_INDEX_COLUMN_BLOCK;
232 public final int SIZE_INDEX_INFO_BLOCK;
233
234 public final int OFFSET_COLUMN_TYPE;
235 public final int OFFSET_COLUMN_NUMBER;
236 public final int OFFSET_COLUMN_PRECISION;
237 public final int OFFSET_COLUMN_SCALE;
238 public final int OFFSET_COLUMN_SORT_ORDER;
239 public final int OFFSET_COLUMN_CODE_PAGE;
240 public final int OFFSET_COLUMN_COMPLEX_ID;
241 public final int OFFSET_COLUMN_FLAGS;
242 public final int OFFSET_COLUMN_EXT_FLAGS;
243 public final int OFFSET_COLUMN_LENGTH;
244 public final int OFFSET_COLUMN_VARIABLE_TABLE_INDEX;
245 public final int OFFSET_COLUMN_FIXED_DATA_OFFSET;
246 public final int OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET;
247
248 public final int OFFSET_TABLE_DEF_LOCATION;
249
250 public final int OFFSET_ROW_START;
251 public final int OFFSET_USAGE_MAP_START;
252
253 public final int OFFSET_USAGE_MAP_PAGE_DATA;
254
255 public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
256
257 public final int OFFSET_FREE_SPACE;
258 public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
259 public final int MAX_NUM_ROWS_ON_DATA_PAGE;
260
261 public final int OFFSET_INDEX_COMPRESSED_BYTE_COUNT;
262 public final int OFFSET_INDEX_ENTRY_MASK;
263 public final int OFFSET_PREV_INDEX_PAGE;
264 public final int OFFSET_NEXT_INDEX_PAGE;
265 public final int OFFSET_CHILD_TAIL_INDEX_PAGE;
266
267 public final int SIZE_INDEX_DEFINITION;
268 public final int SIZE_COLUMN_HEADER;
269 public final int SIZE_ROW_LOCATION;
270 public final int SIZE_LONG_VALUE_DEF;
271 public final int MAX_INLINE_LONG_VALUE_SIZE;
272 public final int MAX_LONG_VALUE_ROW_SIZE;
273 public final int MAX_COMPRESSED_UNICODE_SIZE;
274 public final int SIZE_TDEF_HEADER;
275 public final int SIZE_TDEF_TRAILER;
276 public final int SIZE_COLUMN_DEF_BLOCK;
277 public final int SIZE_INDEX_ENTRY_MASK;
278 public final int SKIP_BEFORE_INDEX_FLAGS;
279 public final int SKIP_AFTER_INDEX_FLAGS;
280 public final int SKIP_BEFORE_INDEX_SLOT;
281 public final int SKIP_AFTER_INDEX_SLOT;
282 public final int SKIP_BEFORE_INDEX;
283 public final int SIZE_NAME_LENGTH;
284 public final int SIZE_ROW_COLUMN_COUNT;
285 public final int SIZE_ROW_VAR_COL_OFFSET;
286
287 public final int USAGE_MAP_TABLE_BYTE_LENGTH;
288
289 public final int MAX_COLUMNS_PER_TABLE;
290 public final int MAX_INDEXES_PER_TABLE;
291 public final int MAX_TABLE_NAME_LENGTH;
292 public final int MAX_COLUMN_NAME_LENGTH;
293 public final int MAX_INDEX_NAME_LENGTH;
294
295 public final boolean LEGACY_NUMERIC_INDEXES;
296
297 public final Charset CHARSET;
298 public final ColumnImpl.SortOrder DEFAULT_SORT_ORDER;
299 public final byte[] PROPERTY_MAP_TYPE;
300 public final int SIZE_TEXT_FIELD_UNIT;
301
302
303
304
305
306
307 public static JetFormat getFormat(FileChannel channel) throws IOException {
308 ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH);
309 int bytesRead = channel.read(buffer, 0L);
310 if(bytesRead < HEADER_LENGTH) {
311 throw new IOException("Empty database file");
312 }
313 buffer.flip();
314 byte version = buffer.get(OFFSET_VERSION);
315 if (version == CODE_VERSION_3) {
316 return VERSION_3;
317 } else if (version == CODE_VERSION_4) {
318 if(ByteUtil.matchesRange(buffer, OFFSET_ENGINE_NAME, MSISAM_ENGINE)) {
319 return VERSION_MSISAM;
320 }
321 return VERSION_4;
322 } else if (version == CODE_VERSION_12) {
323 return VERSION_12;
324 } else if (version == CODE_VERSION_14) {
325 return VERSION_14;
326 } else if (version == CODE_VERSION_16) {
327 return VERSION_16;
328 } else if (version == CODE_VERSION_17) {
329 return VERSION_17;
330 }
331 throw new IOException("Unsupported " +
332 ((version < CODE_VERSION_3) ? "older" : "newer") +
333 " version: " + version);
334 }
335
336 private JetFormat(String name) {
337 _name = name;
338
339 READ_ONLY = defineReadOnly();
340 INDEXES_SUPPORTED = defineIndexesSupported();
341 CODEC_TYPE = defineCodecType();
342
343 PAGE_SIZE = definePageSize();
344 MAX_DATABASE_SIZE = defineMaxDatabaseSize();
345
346 MAX_ROW_SIZE = defineMaxRowSize();
347 DATA_PAGE_INITIAL_FREE_SPACE = defineDataPageInitialFreeSpace();
348
349 OFFSET_MASKED_HEADER = defineOffsetMaskedHeader();
350 HEADER_MASK = defineHeaderMask();
351 OFFSET_HEADER_DATE = defineOffsetHeaderDate();
352 OFFSET_PASSWORD = defineOffsetPassword();
353 SIZE_PASSWORD = defineSizePassword();
354 OFFSET_SORT_ORDER = defineOffsetSortOrder();
355 SIZE_SORT_ORDER = defineSizeSortOrder();
356 OFFSET_CODE_PAGE = defineOffsetCodePage();
357 OFFSET_ENCODING_KEY = defineOffsetEncodingKey();
358 OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
359 OFFSET_NUM_ROWS = defineOffsetNumRows();
360 OFFSET_NEXT_AUTO_NUMBER = defineOffsetNextAutoNumber();
361 OFFSET_NEXT_COMPLEX_AUTO_NUMBER = defineOffsetNextComplexAutoNumber();
362 OFFSET_TABLE_TYPE = defineOffsetTableType();
363 OFFSET_MAX_COLS = defineOffsetMaxCols();
364 OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
365 OFFSET_NUM_COLS = defineOffsetNumCols();
366 OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
367 OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
368 OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
369 OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
370 OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
371
372 SIZE_INDEX_COLUMN_BLOCK = defineSizeIndexColumnBlock();
373 SIZE_INDEX_INFO_BLOCK = defineSizeIndexInfoBlock();
374
375 OFFSET_COLUMN_TYPE = defineOffsetColumnType();
376 OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
377 OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
378 OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
379 OFFSET_COLUMN_SORT_ORDER = defineOffsetColumnSortOrder();
380 OFFSET_COLUMN_CODE_PAGE = defineOffsetColumnCodePage();
381 OFFSET_COLUMN_COMPLEX_ID = defineOffsetColumnComplexId();
382 OFFSET_COLUMN_FLAGS = defineOffsetColumnFlags();
383 OFFSET_COLUMN_EXT_FLAGS = defineOffsetColumnExtFlags();
384 OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
385 OFFSET_COLUMN_VARIABLE_TABLE_INDEX = defineOffsetColumnVariableTableIndex();
386 OFFSET_COLUMN_FIXED_DATA_OFFSET = defineOffsetColumnFixedDataOffset();
387 OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET = defineOffsetColumnFixedDataRowOffset();
388
389 OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
390
391 OFFSET_ROW_START = defineOffsetRowStart();
392 OFFSET_USAGE_MAP_START = defineOffsetUsageMapStart();
393
394 OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
395
396 OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
397
398 OFFSET_FREE_SPACE = defineOffsetFreeSpace();
399 OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
400 MAX_NUM_ROWS_ON_DATA_PAGE = defineMaxNumRowsOnDataPage();
401
402 OFFSET_INDEX_COMPRESSED_BYTE_COUNT = defineOffsetIndexCompressedByteCount();
403 OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
404 OFFSET_PREV_INDEX_PAGE = defineOffsetPrevIndexPage();
405 OFFSET_NEXT_INDEX_PAGE = defineOffsetNextIndexPage();
406 OFFSET_CHILD_TAIL_INDEX_PAGE = defineOffsetChildTailIndexPage();
407
408 SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
409 SIZE_COLUMN_HEADER = defineSizeColumnHeader();
410 SIZE_ROW_LOCATION = defineSizeRowLocation();
411 SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
412 MAX_INLINE_LONG_VALUE_SIZE = defineMaxInlineLongValueSize();
413 MAX_LONG_VALUE_ROW_SIZE = defineMaxLongValueRowSize();
414 MAX_COMPRESSED_UNICODE_SIZE = defineMaxCompressedUnicodeSize();
415 SIZE_TDEF_HEADER = defineSizeTdefHeader();
416 SIZE_TDEF_TRAILER = defineSizeTdefTrailer();
417 SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
418 SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
419 SKIP_BEFORE_INDEX_FLAGS = defineSkipBeforeIndexFlags();
420 SKIP_AFTER_INDEX_FLAGS = defineSkipAfterIndexFlags();
421 SKIP_BEFORE_INDEX_SLOT = defineSkipBeforeIndexSlot();
422 SKIP_AFTER_INDEX_SLOT = defineSkipAfterIndexSlot();
423 SKIP_BEFORE_INDEX = defineSkipBeforeIndex();
424 SIZE_NAME_LENGTH = defineSizeNameLength();
425 SIZE_ROW_COLUMN_COUNT = defineSizeRowColumnCount();
426 SIZE_ROW_VAR_COL_OFFSET = defineSizeRowVarColOffset();
427
428 USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
429
430 MAX_COLUMNS_PER_TABLE = defineMaxColumnsPerTable();
431 MAX_INDEXES_PER_TABLE = defineMaxIndexesPerTable();
432 MAX_TABLE_NAME_LENGTH = defineMaxTableNameLength();
433 MAX_COLUMN_NAME_LENGTH = defineMaxColumnNameLength();
434 MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
435
436 LEGACY_NUMERIC_INDEXES = defineLegacyNumericIndexes();
437
438 CHARSET = defineCharset();
439 DEFAULT_SORT_ORDER = defineDefaultSortOrder();
440 PROPERTY_MAP_TYPE = definePropMapType();
441 SIZE_TEXT_FIELD_UNIT = defineSizeTextFieldUnit();
442 }
443
444 protected abstract boolean defineReadOnly();
445 protected abstract boolean defineIndexesSupported();
446 protected abstract CodecType defineCodecType();
447
448 protected abstract int definePageSize();
449 protected abstract long defineMaxDatabaseSize();
450
451 protected abstract int defineMaxRowSize();
452 protected abstract int defineDataPageInitialFreeSpace();
453
454 protected abstract int defineOffsetMaskedHeader();
455 protected abstract byte[] defineHeaderMask();
456 protected abstract int defineOffsetHeaderDate();
457 protected abstract int defineOffsetPassword();
458 protected abstract int defineSizePassword();
459 protected abstract int defineOffsetSortOrder();
460 protected abstract int defineSizeSortOrder();
461 protected abstract int defineOffsetCodePage();
462 protected abstract int defineOffsetEncodingKey();
463 protected abstract int defineOffsetNextTableDefPage();
464 protected abstract int defineOffsetNumRows();
465 protected abstract int defineOffsetNextAutoNumber();
466 protected abstract int defineOffsetNextComplexAutoNumber();
467 protected abstract int defineOffsetTableType();
468 protected abstract int defineOffsetMaxCols();
469 protected abstract int defineOffsetNumVarCols();
470 protected abstract int defineOffsetNumCols();
471 protected abstract int defineOffsetNumIndexSlots();
472 protected abstract int defineOffsetNumIndexes();
473 protected abstract int defineOffsetOwnedPages();
474 protected abstract int defineOffsetFreeSpacePages();
475 protected abstract int defineOffsetIndexDefBlock();
476
477 protected abstract int defineSizeIndexColumnBlock();
478 protected abstract int defineSizeIndexInfoBlock();
479
480 protected abstract int defineOffsetColumnType();
481 protected abstract int defineOffsetColumnNumber();
482 protected abstract int defineOffsetColumnPrecision();
483 protected abstract int defineOffsetColumnScale();
484 protected abstract int defineOffsetColumnSortOrder();
485 protected abstract int defineOffsetColumnCodePage();
486 protected abstract int defineOffsetColumnComplexId();
487 protected abstract int defineOffsetColumnFlags();
488 protected abstract int defineOffsetColumnExtFlags();
489 protected abstract int defineOffsetColumnLength();
490 protected abstract int defineOffsetColumnVariableTableIndex();
491 protected abstract int defineOffsetColumnFixedDataOffset();
492 protected abstract int defineOffsetColumnFixedDataRowOffset();
493
494 protected abstract int defineOffsetTableDefLocation();
495
496 protected abstract int defineOffsetRowStart();
497 protected abstract int defineOffsetUsageMapStart();
498
499 protected abstract int defineOffsetUsageMapPageData();
500
501 protected abstract int defineOffsetReferenceMapPageNumbers();
502
503 protected abstract int defineOffsetFreeSpace();
504 protected abstract int defineOffsetNumRowsOnDataPage();
505 protected abstract int defineMaxNumRowsOnDataPage();
506
507 protected abstract int defineOffsetIndexCompressedByteCount();
508 protected abstract int defineOffsetIndexEntryMask();
509 protected abstract int defineOffsetPrevIndexPage();
510 protected abstract int defineOffsetNextIndexPage();
511 protected abstract int defineOffsetChildTailIndexPage();
512
513 protected abstract int defineSizeIndexDefinition();
514 protected abstract int defineSizeColumnHeader();
515 protected abstract int defineSizeRowLocation();
516 protected abstract int defineSizeLongValueDef();
517 protected abstract int defineMaxInlineLongValueSize();
518 protected abstract int defineMaxLongValueRowSize();
519 protected abstract int defineMaxCompressedUnicodeSize();
520 protected abstract int defineSizeTdefHeader();
521 protected abstract int defineSizeTdefTrailer();
522 protected abstract int defineSizeColumnDefBlock();
523 protected abstract int defineSizeIndexEntryMask();
524 protected abstract int defineSkipBeforeIndexFlags();
525 protected abstract int defineSkipAfterIndexFlags();
526 protected abstract int defineSkipBeforeIndexSlot();
527 protected abstract int defineSkipAfterIndexSlot();
528 protected abstract int defineSkipBeforeIndex();
529 protected abstract int defineSizeNameLength();
530 protected abstract int defineSizeRowColumnCount();
531 protected abstract int defineSizeRowVarColOffset();
532
533 protected abstract int defineUsageMapTableByteLength();
534
535 protected abstract int defineMaxColumnsPerTable();
536 protected abstract int defineMaxIndexesPerTable();
537 protected abstract int defineMaxTableNameLength();
538 protected abstract int defineMaxColumnNameLength();
539 protected abstract int defineMaxIndexNameLength();
540
541 protected abstract Charset defineCharset();
542 protected abstract ColumnImpl.SortOrder defineDefaultSortOrder();
543 protected abstract byte[] definePropMapType();
544 protected abstract int defineSizeTextFieldUnit();
545
546 protected abstract boolean defineLegacyNumericIndexes();
547
548 protected abstract Map<String,Database.FileFormat> getPossibleFileFormats();
549
550 public abstract boolean isSupportedDataType(DataType type);
551
552 public abstract boolean isSupportedCalculatedDataType(DataType type);
553
554 @Override
555 public String toString() {
556 return _name;
557 }
558
559 private static class Jet3Format extends JetFormat {
560
561 private Jet3Format() {
562 super("VERSION_3");
563 }
564
565 @Override
566 protected boolean defineReadOnly() { return true; }
567
568 @Override
569 protected boolean defineIndexesSupported() { return true; }
570
571 @Override
572 protected CodecType defineCodecType() {
573 return CodecType.JET;
574 }
575
576 @Override
577 protected int definePageSize() { return 2048; }
578
579 @Override
580 protected long defineMaxDatabaseSize() {
581 return (1L * 1024L * 1024L * 1024L);
582 }
583
584 @Override
585 protected int defineMaxRowSize() { return 2012; }
586 @Override
587 protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
588
589 @Override
590 protected int defineOffsetMaskedHeader() { return 24; }
591 @Override
592 protected byte[] defineHeaderMask() {
593 return ByteUtil.copyOf(BASE_HEADER_MASK, BASE_HEADER_MASK.length - 2);
594 }
595 @Override
596 protected int defineOffsetHeaderDate() { return -1; }
597 @Override
598 protected int defineOffsetPassword() { return 66; }
599 @Override
600 protected int defineSizePassword() { return 20; }
601 @Override
602 protected int defineOffsetSortOrder() { return 58; }
603 @Override
604 protected int defineSizeSortOrder() { return 2; }
605 @Override
606 protected int defineOffsetCodePage() { return 60; }
607 @Override
608 protected int defineOffsetEncodingKey() { return 62; }
609 @Override
610 protected int defineOffsetNextTableDefPage() { return 4; }
611 @Override
612 protected int defineOffsetNumRows() { return 12; }
613 @Override
614 protected int defineOffsetNextAutoNumber() { return 20; }
615 @Override
616 protected int defineOffsetNextComplexAutoNumber() { return -1; }
617 @Override
618 protected int defineOffsetTableType() { return 20; }
619 @Override
620 protected int defineOffsetMaxCols() { return 21; }
621 @Override
622 protected int defineOffsetNumVarCols() { return 23; }
623 @Override
624 protected int defineOffsetNumCols() { return 25; }
625 @Override
626 protected int defineOffsetNumIndexSlots() { return 27; }
627 @Override
628 protected int defineOffsetNumIndexes() { return 31; }
629 @Override
630 protected int defineOffsetOwnedPages() { return 35; }
631 @Override
632 protected int defineOffsetFreeSpacePages() { return 39; }
633 @Override
634 protected int defineOffsetIndexDefBlock() { return 43; }
635
636 @Override
637 protected int defineSizeIndexColumnBlock() { return 39; }
638 @Override
639 protected int defineSizeIndexInfoBlock() { return 20; }
640
641 @Override
642 protected int defineOffsetColumnType() { return 0; }
643 @Override
644 protected int defineOffsetColumnNumber() { return 1; }
645 @Override
646 protected int defineOffsetColumnPrecision() { return 11; }
647 @Override
648 protected int defineOffsetColumnScale() { return 12; }
649 @Override
650 protected int defineOffsetColumnSortOrder() { return 9; }
651 @Override
652 protected int defineOffsetColumnCodePage() { return 11; }
653 @Override
654 protected int defineOffsetColumnComplexId() { return -1; }
655 @Override
656 protected int defineOffsetColumnFlags() { return 13; }
657 @Override
658 protected int defineOffsetColumnExtFlags() { return -1; }
659 @Override
660 protected int defineOffsetColumnLength() { return 16; }
661 @Override
662 protected int defineOffsetColumnVariableTableIndex() { return 3; }
663 @Override
664 protected int defineOffsetColumnFixedDataOffset() { return 14; }
665 @Override
666 protected int defineOffsetColumnFixedDataRowOffset() { return 1; }
667
668 @Override
669 protected int defineOffsetTableDefLocation() { return 4; }
670
671 @Override
672 protected int defineOffsetRowStart() { return 10; }
673 @Override
674 protected int defineOffsetUsageMapStart() { return 5; }
675
676 @Override
677 protected int defineOffsetUsageMapPageData() { return 4; }
678
679 @Override
680 protected int defineOffsetReferenceMapPageNumbers() { return 1; }
681
682 @Override
683 protected int defineOffsetFreeSpace() { return 2; }
684 @Override
685 protected int defineOffsetNumRowsOnDataPage() { return 8; }
686 @Override
687 protected int defineMaxNumRowsOnDataPage() { return 255; }
688
689 @Override
690 protected int defineOffsetIndexCompressedByteCount() { return 20; }
691 @Override
692 protected int defineOffsetIndexEntryMask() { return 22; }
693 @Override
694 protected int defineOffsetPrevIndexPage() { return 8; }
695 @Override
696 protected int defineOffsetNextIndexPage() { return 12; }
697 @Override
698 protected int defineOffsetChildTailIndexPage() { return 16; }
699
700 @Override
701 protected int defineSizeIndexDefinition() { return 8; }
702 @Override
703 protected int defineSizeColumnHeader() { return 18; }
704 @Override
705 protected int defineSizeRowLocation() { return 2; }
706 @Override
707 protected int defineSizeLongValueDef() { return 12; }
708 @Override
709 protected int defineMaxInlineLongValueSize() { return 64; }
710 @Override
711 protected int defineMaxLongValueRowSize() { return 2032; }
712 @Override
713 protected int defineMaxCompressedUnicodeSize() { return 1024; }
714 @Override
715 protected int defineSizeTdefHeader() { return 43; }
716 @Override
717 protected int defineSizeTdefTrailer() { return 2; }
718 @Override
719 protected int defineSizeColumnDefBlock() { return 25; }
720 @Override
721 protected int defineSizeIndexEntryMask() { return 226; }
722 @Override
723 protected int defineSkipBeforeIndexFlags() { return 0; }
724 @Override
725 protected int defineSkipAfterIndexFlags() { return 0; }
726 @Override
727 protected int defineSkipBeforeIndexSlot() { return 0; }
728 @Override
729 protected int defineSkipAfterIndexSlot() { return 0; }
730 @Override
731 protected int defineSkipBeforeIndex() { return 0; }
732 @Override
733 protected int defineSizeNameLength() { return 1; }
734 @Override
735 protected int defineSizeRowColumnCount() { return 1; }
736 @Override
737 protected int defineSizeRowVarColOffset() { return 1; }
738
739 @Override
740 protected int defineUsageMapTableByteLength() { return 128; }
741
742 @Override
743 protected int defineMaxColumnsPerTable() { return 255; }
744
745 @Override
746 protected int defineMaxIndexesPerTable() { return 32; }
747
748 @Override
749 protected int defineMaxTableNameLength() { return 64; }
750
751 @Override
752 protected int defineMaxColumnNameLength() { return 64; }
753
754 @Override
755 protected int defineMaxIndexNameLength() { return 64; }
756
757 @Override
758 protected boolean defineLegacyNumericIndexes() { return true; }
759
760 @Override
761 protected Charset defineCharset() { return Charset.defaultCharset(); }
762
763 @Override
764 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
765 return ColumnImpl.GENERAL_97_SORT_ORDER;
766 }
767
768 @Override
769 protected byte[] definePropMapType() {
770 return PROPERTY_MAP_TYPES[1];
771 }
772
773 @Override
774 protected int defineSizeTextFieldUnit() { return 1; }
775
776 @Override
777 protected Map<String,Database.FileFormat> getPossibleFileFormats()
778 {
779 return PossibleFileFormats.POSSIBLE_VERSION_3;
780 }
781
782 @Override
783 public boolean isSupportedDataType(DataType type) {
784 return !V3_UNSUPP_TYPES.contains(type);
785 }
786
787 @Override
788 public boolean isSupportedCalculatedDataType(DataType type) {
789 return false;
790 }
791 }
792
793 private static class Jet4Format extends JetFormat {
794
795 private Jet4Format() {
796 this("VERSION_4");
797 }
798
799 private Jet4Format(String name) {
800 super(name);
801 }
802
803 @Override
804 protected boolean defineReadOnly() { return false; }
805
806 @Override
807 protected boolean defineIndexesSupported() { return true; }
808
809 @Override
810 protected CodecType defineCodecType() {
811 return CodecType.JET;
812 }
813
814 @Override
815 protected int definePageSize() { return 4096; }
816
817 @Override
818 protected long defineMaxDatabaseSize() {
819 return (2L * 1024L * 1024L * 1024L);
820 }
821
822 @Override
823 protected int defineMaxRowSize() { return 4060; }
824 @Override
825 protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
826
827 @Override
828 protected int defineOffsetMaskedHeader() { return 24; }
829 @Override
830 protected byte[] defineHeaderMask() { return BASE_HEADER_MASK; }
831 @Override
832 protected int defineOffsetHeaderDate() { return 114; }
833 @Override
834 protected int defineOffsetPassword() { return 66; }
835 @Override
836 protected int defineSizePassword() { return 40; }
837 @Override
838 protected int defineOffsetSortOrder() { return 110; }
839 @Override
840 protected int defineSizeSortOrder() { return 4; }
841 @Override
842 protected int defineOffsetCodePage() { return 60; }
843 @Override
844 protected int defineOffsetEncodingKey() { return 62; }
845 @Override
846 protected int defineOffsetNextTableDefPage() { return 4; }
847 @Override
848 protected int defineOffsetNumRows() { return 16; }
849 @Override
850 protected int defineOffsetNextAutoNumber() { return 20; }
851 @Override
852 protected int defineOffsetNextComplexAutoNumber() { return -1; }
853 @Override
854 protected int defineOffsetTableType() { return 40; }
855 @Override
856 protected int defineOffsetMaxCols() { return 41; }
857 @Override
858 protected int defineOffsetNumVarCols() { return 43; }
859 @Override
860 protected int defineOffsetNumCols() { return 45; }
861 @Override
862 protected int defineOffsetNumIndexSlots() { return 47; }
863 @Override
864 protected int defineOffsetNumIndexes() { return 51; }
865 @Override
866 protected int defineOffsetOwnedPages() { return 55; }
867 @Override
868 protected int defineOffsetFreeSpacePages() { return 59; }
869 @Override
870 protected int defineOffsetIndexDefBlock() { return 63; }
871
872 @Override
873 protected int defineSizeIndexColumnBlock() { return 52; }
874 @Override
875 protected int defineSizeIndexInfoBlock() { return 28; }
876
877 @Override
878 protected int defineOffsetColumnType() { return 0; }
879 @Override
880 protected int defineOffsetColumnNumber() { return 5; }
881 @Override
882 protected int defineOffsetColumnPrecision() { return 11; }
883 @Override
884 protected int defineOffsetColumnScale() { return 12; }
885 @Override
886 protected int defineOffsetColumnSortOrder() { return 11; }
887 @Override
888 protected int defineOffsetColumnCodePage() { return -1; }
889 @Override
890 protected int defineOffsetColumnComplexId() { return -1; }
891 @Override
892 protected int defineOffsetColumnFlags() { return 15; }
893 @Override
894 protected int defineOffsetColumnExtFlags() { return 16; }
895 @Override
896 protected int defineOffsetColumnLength() { return 23; }
897 @Override
898 protected int defineOffsetColumnVariableTableIndex() { return 7; }
899 @Override
900 protected int defineOffsetColumnFixedDataOffset() { return 21; }
901 @Override
902 protected int defineOffsetColumnFixedDataRowOffset() { return 2; }
903
904 @Override
905 protected int defineOffsetTableDefLocation() { return 4; }
906
907 @Override
908 protected int defineOffsetRowStart() { return 14; }
909 @Override
910 protected int defineOffsetUsageMapStart() { return 5; }
911
912 @Override
913 protected int defineOffsetUsageMapPageData() { return 4; }
914
915 @Override
916 protected int defineOffsetReferenceMapPageNumbers() { return 1; }
917
918 @Override
919 protected int defineOffsetFreeSpace() { return 2; }
920 @Override
921 protected int defineOffsetNumRowsOnDataPage() { return 12; }
922 @Override
923 protected int defineMaxNumRowsOnDataPage() { return 255; }
924
925 @Override
926 protected int defineOffsetIndexCompressedByteCount() { return 24; }
927 @Override
928 protected int defineOffsetIndexEntryMask() { return 27; }
929 @Override
930 protected int defineOffsetPrevIndexPage() { return 12; }
931 @Override
932 protected int defineOffsetNextIndexPage() { return 16; }
933 @Override
934 protected int defineOffsetChildTailIndexPage() { return 20; }
935
936 @Override
937 protected int defineSizeIndexDefinition() { return 12; }
938 @Override
939 protected int defineSizeColumnHeader() { return 25; }
940 @Override
941 protected int defineSizeRowLocation() { return 2; }
942 @Override
943 protected int defineSizeLongValueDef() { return 12; }
944 @Override
945 protected int defineMaxInlineLongValueSize() { return 64; }
946 @Override
947 protected int defineMaxLongValueRowSize() { return 4076; }
948 @Override
949 protected int defineMaxCompressedUnicodeSize() { return 1024; }
950 @Override
951 protected int defineSizeTdefHeader() { return 63; }
952 @Override
953 protected int defineSizeTdefTrailer() { return 2; }
954 @Override
955 protected int defineSizeColumnDefBlock() { return 25; }
956 @Override
957 protected int defineSizeIndexEntryMask() { return 453; }
958 @Override
959 protected int defineSkipBeforeIndexFlags() { return 4; }
960 @Override
961 protected int defineSkipAfterIndexFlags() { return 5; }
962 @Override
963 protected int defineSkipBeforeIndexSlot() { return 4; }
964 @Override
965 protected int defineSkipAfterIndexSlot() { return 4; }
966 @Override
967 protected int defineSkipBeforeIndex() { return 4; }
968 @Override
969 protected int defineSizeNameLength() { return 2; }
970 @Override
971 protected int defineSizeRowColumnCount() { return 2; }
972 @Override
973 protected int defineSizeRowVarColOffset() { return 2; }
974
975 @Override
976 protected int defineUsageMapTableByteLength() { return 64; }
977
978 @Override
979 protected int defineMaxColumnsPerTable() { return 255; }
980
981 @Override
982 protected int defineMaxIndexesPerTable() { return 32; }
983
984 @Override
985 protected int defineMaxTableNameLength() { return 64; }
986
987 @Override
988 protected int defineMaxColumnNameLength() { return 64; }
989
990 @Override
991 protected int defineMaxIndexNameLength() { return 64; }
992
993 @Override
994 protected boolean defineLegacyNumericIndexes() { return true; }
995
996 @Override
997 protected Charset defineCharset() { return StandardCharsets.UTF_16LE; }
998
999 @Override
1000 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
1001 return ColumnImpl.GENERAL_LEGACY_SORT_ORDER;
1002 }
1003
1004 @Override
1005 protected byte[] definePropMapType() {
1006 return PROPERTY_MAP_TYPES[0];
1007 }
1008
1009 @Override
1010 protected int defineSizeTextFieldUnit() { return TEXT_FIELD_UNIT_SIZE; }
1011
1012 @Override
1013 protected Map<String,Database.FileFormat> getPossibleFileFormats()
1014 {
1015 return PossibleFileFormats.POSSIBLE_VERSION_4;
1016 }
1017
1018 @Override
1019 public boolean isSupportedDataType(DataType type) {
1020 return !V3_UNSUPP_TYPES.contains(type);
1021 }
1022
1023 @Override
1024 public boolean isSupportedCalculatedDataType(DataType type) {
1025 return false;
1026 }
1027 }
1028
1029 private static final class MSISAMFormat extends Jet4Format {
1030 private MSISAMFormat() {
1031 super("MSISAM");
1032 }
1033
1034 @Override
1035 protected CodecType defineCodecType() {
1036 return CodecType.MSISAM;
1037 }
1038
1039 @Override
1040 protected Map<String,Database.FileFormat> getPossibleFileFormats()
1041 {
1042 return PossibleFileFormats.POSSIBLE_VERSION_MSISAM;
1043 }
1044 }
1045
1046 private static class Jet12Format extends Jet4Format {
1047 private Jet12Format() {
1048 super("VERSION_12");
1049 }
1050
1051 private Jet12Format(String name) {
1052 super(name);
1053 }
1054
1055 @Override
1056 protected CodecType defineCodecType() {
1057 return CodecType.OFFICE;
1058 }
1059
1060 @Override
1061 protected boolean defineLegacyNumericIndexes() { return false; }
1062
1063 @Override
1064 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1065 return PossibleFileFormats.POSSIBLE_VERSION_12;
1066 }
1067
1068 @Override
1069 protected int defineOffsetNextComplexAutoNumber() { return 28; }
1070
1071 @Override
1072 protected int defineOffsetColumnComplexId() { return 11; }
1073
1074 @Override
1075 public boolean isSupportedDataType(DataType type) {
1076 return !V12_UNSUPP_TYPES.contains(type);
1077 }
1078
1079 @Override
1080 public boolean isSupportedCalculatedDataType(DataType type) {
1081 return false;
1082 }
1083 }
1084
1085 private static class Jet14Format extends Jet12Format {
1086 private Jet14Format() {
1087 super("VERSION_14");
1088 }
1089
1090 private Jet14Format(String name) {
1091 super(name);
1092 }
1093
1094 @Override
1095 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
1096 return ColumnImpl.GENERAL_SORT_ORDER;
1097 }
1098
1099 @Override
1100 protected byte[] definePropMapType() {
1101 return PROPERTY_MAP_TYPES[0];
1102 }
1103
1104 @Override
1105 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1106 return PossibleFileFormats.POSSIBLE_VERSION_14;
1107 }
1108
1109 @Override
1110 public boolean isSupportedCalculatedDataType(DataType type) {
1111 return V14_CALC_TYPES.contains(type);
1112 }
1113 }
1114
1115 private static class Jet16Format extends Jet14Format {
1116
1117 private Jet16Format() {
1118 super("VERSION_16");
1119 }
1120
1121 private Jet16Format(String name) {
1122 super(name);
1123 }
1124
1125 @Override
1126 public boolean isSupportedDataType(DataType type) {
1127 return !V16_UNSUPP_TYPES.contains(type);
1128 }
1129
1130 @Override
1131 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1132 return PossibleFileFormats.POSSIBLE_VERSION_16;
1133 }
1134
1135 @Override
1136 public boolean isSupportedCalculatedDataType(DataType type) {
1137 return V16_CALC_TYPES.contains(type);
1138 }
1139 }
1140
1141 private static final class Jet17Format extends Jet16Format {
1142
1143 private Jet17Format() {
1144 super("VERSION_17");
1145 }
1146
1147 @Override
1148 public boolean isSupportedDataType(DataType type) {
1149 return true;
1150 }
1151
1152 @Override
1153 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1154 return PossibleFileFormats.POSSIBLE_VERSION_17;
1155 }
1156 }
1157
1158 }