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_COMPRESSED_BYTE_COUNT;
310 public final int SIZE_INDEX_ENTRY_MASK;
311 public final int SKIP_BEFORE_INDEX_FLAGS;
312 public final int SKIP_AFTER_INDEX_FLAGS;
313 public final int SKIP_BEFORE_INDEX_SLOT;
314 public final int SKIP_AFTER_INDEX_SLOT;
315 public final int SKIP_BEFORE_INDEX;
316 public final int SIZE_NAME_LENGTH;
317 public final int SIZE_ROW_COLUMN_COUNT;
318 public final int SIZE_ROW_VAR_COL_OFFSET;
319
320 public final int USAGE_MAP_TABLE_BYTE_LENGTH;
321
322 public final int MAX_COLUMNS_PER_TABLE;
323 public final int MAX_INDEXES_PER_TABLE;
324 public final int MAX_TABLE_NAME_LENGTH;
325 public final int MAX_COLUMN_NAME_LENGTH;
326 public final int MAX_INDEX_NAME_LENGTH;
327
328 public final boolean LEGACY_NUMERIC_INDEXES;
329
330 public final Charset CHARSET;
331
332
333 public final boolean CODE_PAGE_CHARSET;
334 public final ColumnImpl.SortOrder DEFAULT_SORT_ORDER;
335 public final byte[] PROPERTY_MAP_TYPE;
336 public final int SIZE_TEXT_FIELD_UNIT;
337
338
339
340
341
342
343 public static JetFormat getFormat(FileChannel channel) throws IOException {
344 ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH);
345 int bytesRead = channel.read(buffer, 0L);
346 if(bytesRead < HEADER_LENGTH) {
347 throw new IOException("Empty database file");
348 }
349 buffer.flip();
350 int version = ByteUtil.getUnsignedByte(buffer, OFFSET_VERSION);
351 if (version == CODE_VERSION_3) {
352 return VERSION_3;
353 } else if (version == CODE_VERSION_4) {
354 if(ByteUtil.matchesRange(buffer, OFFSET_ENGINE_NAME, MSISAM_ENGINE)) {
355 return VERSION_MSISAM;
356 }
357 return VERSION_4;
358 } else if (version == CODE_VERSION_2007) {
359 return VERSION_2007;
360 } else if (version == CODE_VERSION_2010) {
361 return VERSION_2010;
362 } else if (version == CODE_VERSION_2016) {
363 return VERSION_2016;
364 } else if (version == CODE_VERSION_2019) {
365 return VERSION_2019;
366 }
367 throw new IOException("Unsupported version: " + version);
368 }
369
370 private JetFormat(String name) {
371 _name = name;
372
373 READ_ONLY = defineReadOnly();
374 INDEXES_SUPPORTED = defineIndexesSupported();
375 CODEC_TYPE = defineCodecType();
376
377 PAGE_SIZE = definePageSize();
378 MAX_DATABASE_SIZE = defineMaxDatabaseSize();
379
380 MAX_ROW_SIZE = defineMaxRowSize();
381 DATA_PAGE_INITIAL_FREE_SPACE = defineDataPageInitialFreeSpace();
382
383 OFFSET_MASKED_HEADER = defineOffsetMaskedHeader();
384 HEADER_MASK = defineHeaderMask();
385 OFFSET_HEADER_DATE = defineOffsetHeaderDate();
386 OFFSET_PASSWORD = defineOffsetPassword();
387 SIZE_PASSWORD = defineSizePassword();
388 OFFSET_SORT_ORDER = defineOffsetSortOrder();
389 SIZE_SORT_ORDER = defineSizeSortOrder();
390 OFFSET_CODE_PAGE = defineOffsetCodePage();
391 OFFSET_ENCODING_KEY = defineOffsetEncodingKey();
392 OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
393 OFFSET_NUM_ROWS = defineOffsetNumRows();
394 OFFSET_NEXT_AUTO_NUMBER = defineOffsetNextAutoNumber();
395 OFFSET_NEXT_COMPLEX_AUTO_NUMBER = defineOffsetNextComplexAutoNumber();
396 OFFSET_TABLE_TYPE = defineOffsetTableType();
397 OFFSET_MAX_COLS = defineOffsetMaxCols();
398 OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
399 OFFSET_NUM_COLS = defineOffsetNumCols();
400 OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
401 OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
402 OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
403 OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
404 OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
405
406 SIZE_INDEX_COLUMN_BLOCK = defineSizeIndexColumnBlock();
407 SIZE_INDEX_INFO_BLOCK = defineSizeIndexInfoBlock();
408
409 OFFSET_COLUMN_TYPE = defineOffsetColumnType();
410 OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
411 OFFSET_COLUMN_ID = defineOffsetColumnId();
412 OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
413 OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
414 OFFSET_COLUMN_SORT_ORDER = defineOffsetColumnSortOrder();
415 OFFSET_COLUMN_CODE_PAGE = defineOffsetColumnCodePage();
416 OFFSET_COLUMN_COMPLEX_ID = defineOffsetColumnComplexId();
417 OFFSET_COLUMN_FLAGS = defineOffsetColumnFlags();
418 OFFSET_COLUMN_EXT_FLAGS = defineOffsetColumnExtFlags();
419 OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
420 OFFSET_COLUMN_VARIABLE_TABLE_INDEX = defineOffsetColumnVariableTableIndex();
421 OFFSET_COLUMN_FIXED_DATA_OFFSET = defineOffsetColumnFixedDataOffset();
422 OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET = defineOffsetColumnFixedDataRowOffset();
423
424 OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
425
426 OFFSET_ROW_START = defineOffsetRowStart();
427 OFFSET_USAGE_MAP_START = defineOffsetUsageMapStart();
428
429 OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
430
431 OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
432
433 OFFSET_FREE_SPACE = defineOffsetFreeSpace();
434 OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
435 MAX_NUM_ROWS_ON_DATA_PAGE = defineMaxNumRowsOnDataPage();
436
437 OFFSET_INDEX_COMPRESSED_BYTE_COUNT = defineOffsetIndexCompressedByteCount();
438 OFFSET_INDEX_LEVEL = defineOffsetIndexLevel();
439 OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
440 OFFSET_PREV_INDEX_PAGE = defineOffsetPrevIndexPage();
441 OFFSET_NEXT_INDEX_PAGE = defineOffsetNextIndexPage();
442 OFFSET_CHILD_TAIL_INDEX_PAGE = defineOffsetChildTailIndexPage();
443
444 SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
445 SIZE_COLUMN_HEADER = defineSizeColumnHeader();
446 SIZE_ROW_LOCATION = defineSizeRowLocation();
447 SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
448 MAX_INLINE_LONG_VALUE_SIZE = defineMaxInlineLongValueSize();
449 MAX_LONG_VALUE_ROW_SIZE = defineMaxLongValueRowSize();
450 MAX_COMPRESSED_UNICODE_SIZE = defineMaxCompressedUnicodeSize();
451 SIZE_TDEF_HEADER = defineSizeTdefHeader();
452 SIZE_TDEF_TRAILER = defineSizeTdefTrailer();
453 SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
454 SIZE_INDEX_COMPRESSED_BYTE_COUNT = defineSizeIndexCompressedByteCount();
455 SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
456 SKIP_BEFORE_INDEX_FLAGS = defineSkipBeforeIndexFlags();
457 SKIP_AFTER_INDEX_FLAGS = defineSkipAfterIndexFlags();
458 SKIP_BEFORE_INDEX_SLOT = defineSkipBeforeIndexSlot();
459 SKIP_AFTER_INDEX_SLOT = defineSkipAfterIndexSlot();
460 SKIP_BEFORE_INDEX = defineSkipBeforeIndex();
461 SIZE_NAME_LENGTH = defineSizeNameLength();
462 SIZE_ROW_COLUMN_COUNT = defineSizeRowColumnCount();
463 SIZE_ROW_VAR_COL_OFFSET = defineSizeRowVarColOffset();
464
465 USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
466
467 MAX_COLUMNS_PER_TABLE = defineMaxColumnsPerTable();
468 MAX_INDEXES_PER_TABLE = defineMaxIndexesPerTable();
469 MAX_TABLE_NAME_LENGTH = defineMaxTableNameLength();
470 MAX_COLUMN_NAME_LENGTH = defineMaxColumnNameLength();
471 MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
472
473 LEGACY_NUMERIC_INDEXES = defineLegacyNumericIndexes();
474
475 CHARSET = defineCharset();
476 CODE_PAGE_CHARSET = defineCodePageCharset();
477 DEFAULT_SORT_ORDER = defineDefaultSortOrder();
478 PROPERTY_MAP_TYPE = definePropMapType();
479 SIZE_TEXT_FIELD_UNIT = defineSizeTextFieldUnit();
480 }
481
482 protected abstract boolean defineReadOnly();
483 protected abstract boolean defineIndexesSupported();
484 protected abstract CodecType defineCodecType();
485
486 protected abstract int definePageSize();
487 protected abstract long defineMaxDatabaseSize();
488
489 protected abstract int defineMaxRowSize();
490 protected abstract int defineDataPageInitialFreeSpace();
491
492 protected abstract int defineOffsetMaskedHeader();
493 protected abstract byte[] defineHeaderMask();
494 protected abstract int defineOffsetHeaderDate();
495 protected abstract int defineOffsetPassword();
496 protected abstract int defineSizePassword();
497 protected abstract int defineOffsetSortOrder();
498 protected abstract int defineSizeSortOrder();
499 protected abstract int defineOffsetCodePage();
500 protected abstract int defineOffsetEncodingKey();
501 protected abstract int defineOffsetNextTableDefPage();
502 protected abstract int defineOffsetNumRows();
503 protected abstract int defineOffsetNextAutoNumber();
504 protected abstract int defineOffsetNextComplexAutoNumber();
505 protected abstract int defineOffsetTableType();
506 protected abstract int defineOffsetMaxCols();
507 protected abstract int defineOffsetNumVarCols();
508 protected abstract int defineOffsetNumCols();
509 protected abstract int defineOffsetNumIndexSlots();
510 protected abstract int defineOffsetNumIndexes();
511 protected abstract int defineOffsetOwnedPages();
512 protected abstract int defineOffsetFreeSpacePages();
513 protected abstract int defineOffsetIndexDefBlock();
514
515 protected abstract int defineSizeIndexColumnBlock();
516 protected abstract int defineSizeIndexInfoBlock();
517
518 protected abstract int defineOffsetColumnType();
519 protected abstract int defineOffsetColumnNumber();
520 protected abstract int defineOffsetColumnId();
521 protected abstract int defineOffsetColumnPrecision();
522 protected abstract int defineOffsetColumnScale();
523 protected abstract int defineOffsetColumnSortOrder();
524 protected abstract int defineOffsetColumnCodePage();
525 protected abstract int defineOffsetColumnComplexId();
526 protected abstract int defineOffsetColumnFlags();
527 protected abstract int defineOffsetColumnExtFlags();
528 protected abstract int defineOffsetColumnLength();
529 protected abstract int defineOffsetColumnVariableTableIndex();
530 protected abstract int defineOffsetColumnFixedDataOffset();
531 protected abstract int defineOffsetColumnFixedDataRowOffset();
532
533 protected abstract int defineOffsetTableDefLocation();
534
535 protected abstract int defineOffsetRowStart();
536 protected abstract int defineOffsetUsageMapStart();
537
538 protected abstract int defineOffsetUsageMapPageData();
539
540 protected abstract int defineOffsetReferenceMapPageNumbers();
541
542 protected abstract int defineOffsetFreeSpace();
543 protected abstract int defineOffsetNumRowsOnDataPage();
544 protected abstract int defineMaxNumRowsOnDataPage();
545
546 protected abstract int defineOffsetIndexCompressedByteCount();
547
548 protected abstract int defineOffsetIndexLevel();
549 protected abstract int defineOffsetIndexEntryMask();
550 protected abstract int defineOffsetPrevIndexPage();
551 protected abstract int defineOffsetNextIndexPage();
552 protected abstract int defineOffsetChildTailIndexPage();
553
554 protected abstract int defineSizeIndexDefinition();
555 protected abstract int defineSizeColumnHeader();
556 protected abstract int defineSizeRowLocation();
557 protected abstract int defineSizeLongValueDef();
558 protected abstract int defineMaxInlineLongValueSize();
559 protected abstract int defineMaxLongValueRowSize();
560 protected abstract int defineMaxCompressedUnicodeSize();
561 protected abstract int defineSizeTdefHeader();
562 protected abstract int defineSizeTdefTrailer();
563 protected abstract int defineSizeColumnDefBlock();
564 protected abstract int defineSizeIndexCompressedByteCount();
565 protected abstract int defineSizeIndexEntryMask();
566 protected abstract int defineSkipBeforeIndexFlags();
567 protected abstract int defineSkipAfterIndexFlags();
568 protected abstract int defineSkipBeforeIndexSlot();
569 protected abstract int defineSkipAfterIndexSlot();
570 protected abstract int defineSkipBeforeIndex();
571 protected abstract int defineSizeNameLength();
572 protected abstract int defineSizeRowColumnCount();
573 protected abstract int defineSizeRowVarColOffset();
574
575 protected abstract int defineUsageMapTableByteLength();
576
577 protected abstract int defineMaxColumnsPerTable();
578 protected abstract int defineMaxIndexesPerTable();
579 protected abstract int defineMaxTableNameLength();
580 protected abstract int defineMaxColumnNameLength();
581 protected abstract int defineMaxIndexNameLength();
582
583 protected abstract Charset defineCharset();
584 protected abstract boolean defineCodePageCharset();
585 protected abstract ColumnImpl.SortOrder defineDefaultSortOrder();
586 protected abstract byte[] definePropMapType();
587 protected abstract int defineSizeTextFieldUnit();
588
589 protected abstract boolean defineLegacyNumericIndexes();
590
591 protected abstract Map<String,Database.FileFormat> getPossibleFileFormats();
592
593 public abstract boolean isSupportedDataType(DataType type);
594
595 public abstract boolean isSupportedCalculatedDataType(DataType type);
596
597 @Override
598 public String toString() {
599 return _name;
600 }
601
602 private static class Jet3Format extends JetFormat {
603
604 private Jet3Format() {
605 super("VERSION_3");
606 }
607
608 @Override
609 protected boolean defineReadOnly() { return true; }
610
611 @Override
612 protected boolean defineIndexesSupported() { return true; }
613
614 @Override
615 protected CodecType defineCodecType() {
616 return CodecType.JET;
617 }
618
619 @Override
620 protected int definePageSize() { return 2048; }
621
622 @Override
623 protected long defineMaxDatabaseSize() {
624 return (1L * 1024L * 1024L * 1024L);
625 }
626
627 @Override
628 protected int defineMaxRowSize() { return 2012; }
629 @Override
630 protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
631
632 @Override
633 protected int defineOffsetMaskedHeader() { return 24; }
634 @Override
635 protected byte[] defineHeaderMask() {
636 return ByteUtil.copyOf(BASE_HEADER_MASK, BASE_HEADER_MASK.length - 2);
637 }
638 @Override
639 protected int defineOffsetHeaderDate() { return -1; }
640 @Override
641 protected int defineOffsetPassword() { return 66; }
642 @Override
643 protected int defineSizePassword() { return 20; }
644 @Override
645 protected int defineOffsetSortOrder() { return 58; }
646 @Override
647 protected int defineSizeSortOrder() { return 2; }
648 @Override
649 protected int defineOffsetCodePage() { return 60; }
650 @Override
651 protected int defineOffsetEncodingKey() { return 62; }
652 @Override
653 protected int defineOffsetNextTableDefPage() { return 4; }
654 @Override
655 protected int defineOffsetNumRows() { return 12; }
656 @Override
657 protected int defineOffsetNextAutoNumber() { return 16; }
658 @Override
659 protected int defineOffsetNextComplexAutoNumber() { return -1; }
660 @Override
661 protected int defineOffsetTableType() { return 20; }
662 @Override
663 protected int defineOffsetMaxCols() { return 21; }
664 @Override
665 protected int defineOffsetNumVarCols() { return 23; }
666 @Override
667 protected int defineOffsetNumCols() { return 25; }
668 @Override
669 protected int defineOffsetNumIndexSlots() { return 27; }
670 @Override
671 protected int defineOffsetNumIndexes() { return 31; }
672 @Override
673 protected int defineOffsetOwnedPages() { return 35; }
674 @Override
675 protected int defineOffsetFreeSpacePages() { return 39; }
676 @Override
677 protected int defineOffsetIndexDefBlock() { return 43; }
678
679 @Override
680 protected int defineSizeIndexColumnBlock() { return 39; }
681 @Override
682 protected int defineSizeIndexInfoBlock() { return 20; }
683
684 @Override
685 protected int defineOffsetColumnType() { return 0; }
686 @Override
687 protected int defineOffsetColumnNumber() { return 1; }
688 @Override
689 protected int defineOffsetColumnId() { return 5; }
690 @Override
691 protected int defineOffsetColumnPrecision() { return 11; }
692 @Override
693 protected int defineOffsetColumnScale() { return 12; }
694 @Override
695 protected int defineOffsetColumnSortOrder() { return 9; }
696 @Override
697 protected int defineOffsetColumnCodePage() { return 11; }
698 @Override
699 protected int defineOffsetColumnComplexId() { return -1; }
700 @Override
701 protected int defineOffsetColumnFlags() { return 13; }
702 @Override
703 protected int defineOffsetColumnExtFlags() { return -1; }
704 @Override
705 protected int defineOffsetColumnLength() { return 16; }
706 @Override
707 protected int defineOffsetColumnVariableTableIndex() { return 3; }
708 @Override
709 protected int defineOffsetColumnFixedDataOffset() { return 14; }
710 @Override
711 protected int defineOffsetColumnFixedDataRowOffset() { return 1; }
712
713 @Override
714 protected int defineOffsetTableDefLocation() { return 4; }
715
716 @Override
717 protected int defineOffsetRowStart() { return 10; }
718 @Override
719 protected int defineOffsetUsageMapStart() { return 5; }
720
721 @Override
722 protected int defineOffsetUsageMapPageData() { return 4; }
723
724 @Override
725 protected int defineOffsetReferenceMapPageNumbers() { return 1; }
726
727 @Override
728 protected int defineOffsetFreeSpace() { return 2; }
729 @Override
730 protected int defineOffsetNumRowsOnDataPage() { return 8; }
731 @Override
732 protected int defineMaxNumRowsOnDataPage() { return 255; }
733
734 @Override
735 protected int defineOffsetIndexCompressedByteCount() { return 20; }
736 @Override
737 protected int defineSizeIndexCompressedByteCount() { return 1; }
738 @Override
739 protected int defineOffsetIndexLevel() { return 21; }
740 @Override
741 protected int defineOffsetIndexEntryMask() { return 22; }
742 @Override
743 protected int defineOffsetPrevIndexPage() { return 8; }
744 @Override
745 protected int defineOffsetNextIndexPage() { return 12; }
746 @Override
747 protected int defineOffsetChildTailIndexPage() { return 16; }
748
749 @Override
750 protected int defineSizeIndexDefinition() { return 8; }
751 @Override
752 protected int defineSizeColumnHeader() { return 18; }
753 @Override
754 protected int defineSizeRowLocation() { return 2; }
755 @Override
756 protected int defineSizeLongValueDef() { return 12; }
757 @Override
758 protected int defineMaxInlineLongValueSize() { return 64; }
759 @Override
760 protected int defineMaxLongValueRowSize() { return 2032; }
761 @Override
762 protected int defineMaxCompressedUnicodeSize() { return 1024; }
763 @Override
764 protected int defineSizeTdefHeader() { return 43; }
765 @Override
766 protected int defineSizeTdefTrailer() { return 2; }
767 @Override
768 protected int defineSizeColumnDefBlock() { return 25; }
769 @Override
770 protected int defineSizeIndexEntryMask() { return 226; }
771 @Override
772 protected int defineSkipBeforeIndexFlags() { return 0; }
773 @Override
774 protected int defineSkipAfterIndexFlags() { return 0; }
775 @Override
776 protected int defineSkipBeforeIndexSlot() { return 0; }
777 @Override
778 protected int defineSkipAfterIndexSlot() { return 0; }
779 @Override
780 protected int defineSkipBeforeIndex() { return 0; }
781 @Override
782 protected int defineSizeNameLength() { return 1; }
783 @Override
784 protected int defineSizeRowColumnCount() { return 1; }
785 @Override
786 protected int defineSizeRowVarColOffset() { return 1; }
787
788 @Override
789 protected int defineUsageMapTableByteLength() { return 128; }
790
791 @Override
792 protected int defineMaxColumnsPerTable() { return 255; }
793
794 @Override
795 protected int defineMaxIndexesPerTable() { return 32; }
796
797 @Override
798 protected int defineMaxTableNameLength() { return 64; }
799
800 @Override
801 protected int defineMaxColumnNameLength() { return 64; }
802
803 @Override
804 protected int defineMaxIndexNameLength() { return 64; }
805
806 @Override
807 protected boolean defineLegacyNumericIndexes() { return true; }
808
809 @Override
810 protected Charset defineCharset() {
811
812
813
814 return Charset.defaultCharset();
815 }
816
817 @Override
818 protected boolean defineCodePageCharset() { return true; }
819
820 @Override
821 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
822 return ColumnImpl.GENERAL_97_SORT_ORDER;
823 }
824
825 @Override
826 protected byte[] definePropMapType() {
827 return PROPERTY_MAP_TYPES[1];
828 }
829
830 @Override
831 protected int defineSizeTextFieldUnit() { return 1; }
832
833 @Override
834 protected Map<String,Database.FileFormat> getPossibleFileFormats()
835 {
836 return PossibleFileFormats.POSSIBLE_VERSION_3;
837 }
838
839 @Override
840 public boolean isSupportedDataType(DataType type) {
841 return !V3_UNSUPP_TYPES.contains(type);
842 }
843
844 @Override
845 public boolean isSupportedCalculatedDataType(DataType type) {
846 return false;
847 }
848 }
849
850 private static class Jet4Format extends JetFormat {
851
852 private Jet4Format() {
853 this("VERSION_4");
854 }
855
856 private Jet4Format(String name) {
857 super(name);
858 }
859
860 @Override
861 protected boolean defineReadOnly() { return false; }
862
863 @Override
864 protected boolean defineIndexesSupported() { return true; }
865
866 @Override
867 protected CodecType defineCodecType() {
868 return CodecType.JET;
869 }
870
871 @Override
872 protected int definePageSize() { return 4096; }
873
874 @Override
875 protected long defineMaxDatabaseSize() {
876 return (2L * 1024L * 1024L * 1024L);
877 }
878
879 @Override
880 protected int defineMaxRowSize() { return 4060; }
881 @Override
882 protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
883
884 @Override
885 protected int defineOffsetMaskedHeader() { return 24; }
886 @Override
887 protected byte[] defineHeaderMask() { return BASE_HEADER_MASK; }
888 @Override
889 protected int defineOffsetHeaderDate() { return 114; }
890 @Override
891 protected int defineOffsetPassword() { return 66; }
892 @Override
893 protected int defineSizePassword() { return 40; }
894 @Override
895 protected int defineOffsetSortOrder() { return 110; }
896 @Override
897 protected int defineSizeSortOrder() { return 4; }
898 @Override
899 protected int defineOffsetCodePage() { return 60; }
900 @Override
901 protected int defineOffsetEncodingKey() { return 62; }
902 @Override
903 protected int defineOffsetNextTableDefPage() { return 4; }
904 @Override
905 protected int defineOffsetNumRows() { return 16; }
906 @Override
907 protected int defineOffsetNextAutoNumber() { return 20; }
908 @Override
909 protected int defineOffsetNextComplexAutoNumber() { return -1; }
910 @Override
911 protected int defineOffsetTableType() { return 40; }
912 @Override
913 protected int defineOffsetMaxCols() { return 41; }
914 @Override
915 protected int defineOffsetNumVarCols() { return 43; }
916 @Override
917 protected int defineOffsetNumCols() { return 45; }
918 @Override
919 protected int defineOffsetNumIndexSlots() { return 47; }
920 @Override
921 protected int defineOffsetNumIndexes() { return 51; }
922 @Override
923 protected int defineOffsetOwnedPages() { return 55; }
924 @Override
925 protected int defineOffsetFreeSpacePages() { return 59; }
926 @Override
927 protected int defineOffsetIndexDefBlock() { return 63; }
928
929 @Override
930 protected int defineSizeIndexColumnBlock() { return 52; }
931 @Override
932 protected int defineSizeIndexInfoBlock() { return 28; }
933
934 @Override
935 protected int defineOffsetColumnType() { return 0; }
936 @Override
937 protected int defineOffsetColumnNumber() { return 5; }
938 @Override
939 protected int defineOffsetColumnId() { return 9; }
940 @Override
941 protected int defineOffsetColumnPrecision() { return 11; }
942 @Override
943 protected int defineOffsetColumnScale() { return 12; }
944 @Override
945 protected int defineOffsetColumnSortOrder() { return 11; }
946 @Override
947 protected int defineOffsetColumnCodePage() { return -1; }
948 @Override
949 protected int defineOffsetColumnComplexId() { return -1; }
950 @Override
951 protected int defineOffsetColumnFlags() { return 15; }
952 @Override
953 protected int defineOffsetColumnExtFlags() { return 16; }
954 @Override
955 protected int defineOffsetColumnLength() { return 23; }
956 @Override
957 protected int defineOffsetColumnVariableTableIndex() { return 7; }
958 @Override
959 protected int defineOffsetColumnFixedDataOffset() { return 21; }
960 @Override
961 protected int defineOffsetColumnFixedDataRowOffset() { return 2; }
962
963 @Override
964 protected int defineOffsetTableDefLocation() { return 4; }
965
966 @Override
967 protected int defineOffsetRowStart() { return 14; }
968 @Override
969 protected int defineOffsetUsageMapStart() { return 5; }
970
971 @Override
972 protected int defineOffsetUsageMapPageData() { return 4; }
973
974 @Override
975 protected int defineOffsetReferenceMapPageNumbers() { return 1; }
976
977 @Override
978 protected int defineOffsetFreeSpace() { return 2; }
979 @Override
980 protected int defineOffsetNumRowsOnDataPage() { return 12; }
981 @Override
982 protected int defineMaxNumRowsOnDataPage() { return 255; }
983
984 @Override
985 protected int defineOffsetIndexCompressedByteCount() { return 24; }
986 @Override
987 protected int defineSizeIndexCompressedByteCount() { return 2; }
988 @Override
989 protected int defineOffsetIndexLevel() { return 26; }
990 @Override
991 protected int defineOffsetIndexEntryMask() { return 27; }
992 @Override
993 protected int defineOffsetPrevIndexPage() { return 12; }
994 @Override
995 protected int defineOffsetNextIndexPage() { return 16; }
996 @Override
997 protected int defineOffsetChildTailIndexPage() { return 20; }
998
999 @Override
1000 protected int defineSizeIndexDefinition() { return 12; }
1001 @Override
1002 protected int defineSizeColumnHeader() { return 25; }
1003 @Override
1004 protected int defineSizeRowLocation() { return 2; }
1005 @Override
1006 protected int defineSizeLongValueDef() { return 12; }
1007 @Override
1008 protected int defineMaxInlineLongValueSize() { return 64; }
1009 @Override
1010 protected int defineMaxLongValueRowSize() { return 4076; }
1011 @Override
1012 protected int defineMaxCompressedUnicodeSize() { return 1024; }
1013 @Override
1014 protected int defineSizeTdefHeader() { return 63; }
1015 @Override
1016 protected int defineSizeTdefTrailer() { return 2; }
1017 @Override
1018 protected int defineSizeColumnDefBlock() { return 25; }
1019 @Override
1020 protected int defineSizeIndexEntryMask() { return 453; }
1021 @Override
1022 protected int defineSkipBeforeIndexFlags() { return 4; }
1023 @Override
1024 protected int defineSkipAfterIndexFlags() { return 5; }
1025 @Override
1026 protected int defineSkipBeforeIndexSlot() { return 4; }
1027 @Override
1028 protected int defineSkipAfterIndexSlot() { return 4; }
1029 @Override
1030 protected int defineSkipBeforeIndex() { return 4; }
1031 @Override
1032 protected int defineSizeNameLength() { return 2; }
1033 @Override
1034 protected int defineSizeRowColumnCount() { return 2; }
1035 @Override
1036 protected int defineSizeRowVarColOffset() { return 2; }
1037
1038 @Override
1039 protected int defineUsageMapTableByteLength() { return 64; }
1040
1041 @Override
1042 protected int defineMaxColumnsPerTable() { return 255; }
1043
1044 @Override
1045 protected int defineMaxIndexesPerTable() { return 32; }
1046
1047 @Override
1048 protected int defineMaxTableNameLength() { return 64; }
1049
1050 @Override
1051 protected int defineMaxColumnNameLength() { return 64; }
1052
1053 @Override
1054 protected int defineMaxIndexNameLength() { return 64; }
1055
1056 @Override
1057 protected boolean defineLegacyNumericIndexes() { return true; }
1058
1059 @Override
1060 protected Charset defineCharset() { return StandardCharsets.UTF_16LE; }
1061
1062 @Override
1063 protected boolean defineCodePageCharset() { return false; }
1064
1065 @Override
1066 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
1067 return ColumnImpl.GENERAL_LEGACY_SORT_ORDER;
1068 }
1069
1070 @Override
1071 protected byte[] definePropMapType() {
1072 return PROPERTY_MAP_TYPES[0];
1073 }
1074
1075 @Override
1076 protected int defineSizeTextFieldUnit() { return TEXT_FIELD_UNIT_SIZE; }
1077
1078 @Override
1079 protected Map<String,Database.FileFormat> getPossibleFileFormats()
1080 {
1081 return PossibleFileFormats.POSSIBLE_VERSION_4;
1082 }
1083
1084 @Override
1085 public boolean isSupportedDataType(DataType type) {
1086 return !V3_UNSUPP_TYPES.contains(type);
1087 }
1088
1089 @Override
1090 public boolean isSupportedCalculatedDataType(DataType type) {
1091 return false;
1092 }
1093 }
1094
1095 private static final class MSISAMFormat extends Jet4Format {
1096 private MSISAMFormat() {
1097 super("MSISAM");
1098 }
1099
1100 @Override
1101 protected CodecType defineCodecType() {
1102 return CodecType.MSISAM;
1103 }
1104
1105 @Override
1106 protected Map<String,Database.FileFormat> getPossibleFileFormats()
1107 {
1108 return PossibleFileFormats.POSSIBLE_VERSION_MSISAM;
1109 }
1110 }
1111
1112 private static class Jet2007Format extends Jet4Format {
1113 private Jet2007Format() {
1114 super("VERSION_2007");
1115 }
1116
1117 private Jet2007Format(String name) {
1118 super(name);
1119 }
1120
1121 @Override
1122 protected CodecType defineCodecType() {
1123 return CodecType.OFFICE;
1124 }
1125
1126 @Override
1127 protected boolean defineLegacyNumericIndexes() { return false; }
1128
1129 @Override
1130 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1131 return PossibleFileFormats.POSSIBLE_VERSION_2007;
1132 }
1133
1134 @Override
1135 protected int defineOffsetNextComplexAutoNumber() { return 28; }
1136
1137 @Override
1138 protected int defineOffsetColumnComplexId() { return 11; }
1139
1140 @Override
1141 public boolean isSupportedDataType(DataType type) {
1142 return !V12_UNSUPP_TYPES.contains(type);
1143 }
1144
1145 @Override
1146 public boolean isSupportedCalculatedDataType(DataType type) {
1147 return false;
1148 }
1149 }
1150
1151 private static class Jet2010Format extends Jet2007Format {
1152 private Jet2010Format() {
1153 super("VERSION_2010");
1154 }
1155
1156 private Jet2010Format(String name) {
1157 super(name);
1158 }
1159
1160 @Override
1161 protected ColumnImpl.SortOrder defineDefaultSortOrder() {
1162 return ColumnImpl.GENERAL_SORT_ORDER;
1163 }
1164
1165 @Override
1166 protected byte[] definePropMapType() {
1167 return PROPERTY_MAP_TYPES[0];
1168 }
1169
1170 @Override
1171 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1172 return PossibleFileFormats.POSSIBLE_VERSION_2010;
1173 }
1174
1175 @Override
1176 public boolean isSupportedCalculatedDataType(DataType type) {
1177 return V14_CALC_TYPES.contains(type);
1178 }
1179 }
1180
1181 private static class Jet2016Format extends Jet2010Format {
1182
1183 private Jet2016Format() {
1184 super("VERSION_2016");
1185 }
1186
1187 private Jet2016Format(String name) {
1188 super(name);
1189 }
1190
1191 @Override
1192 public boolean isSupportedDataType(DataType type) {
1193 return !V16_UNSUPP_TYPES.contains(type);
1194 }
1195
1196 @Override
1197 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1198 return PossibleFileFormats.POSSIBLE_VERSION_2016;
1199 }
1200
1201 @Override
1202 public boolean isSupportedCalculatedDataType(DataType type) {
1203 return V16_CALC_TYPES.contains(type);
1204 }
1205 }
1206
1207 private static final class Jet2019Format extends Jet2016Format {
1208
1209 private Jet2019Format() {
1210 super("VERSION_2019");
1211 }
1212
1213 @Override
1214 public boolean isSupportedDataType(DataType type) {
1215 return true;
1216 }
1217
1218 @Override
1219 protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1220 return PossibleFileFormats.POSSIBLE_VERSION_2019;
1221 }
1222 }
1223
1224 }