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