1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package com.healthmarketscience.jackcess;
29
30 import java.io.IOException;
31 import java.nio.ByteBuffer;
32 import java.nio.channels.FileChannel;
33 import java.nio.charset.Charset;
34
35
36
37
38
39 public abstract class JetFormat {
40
41
42 public static final int MAX_RECORD_SIZE = 1900;
43
44
45 public static final short TEXT_FIELD_UNIT_SIZE = 2;
46
47 public static final short TEXT_FIELD_MAX_LENGTH = 255 * TEXT_FIELD_UNIT_SIZE;
48
49
50 private static final long OFFSET_VERSION = 20L;
51
52 private static final byte CODE_VERSION_3 = 0x0;
53
54 private static final byte CODE_VERSION_4 = 0x1;
55
56
57
58
59
60
61 private final String _name;
62
63
64 public final int PAGE_SIZE;
65 public final long MAX_DATABASE_SIZE;
66
67 public final int MAX_ROW_SIZE;
68 public final int PAGE_INITIAL_FREE_SPACE;
69
70 public final int OFFSET_NEXT_TABLE_DEF_PAGE;
71 public final int OFFSET_NUM_ROWS;
72 public final int OFFSET_NEXT_AUTO_NUMBER;
73 public final int OFFSET_TABLE_TYPE;
74 public final int OFFSET_MAX_COLS;
75 public final int OFFSET_NUM_VAR_COLS;
76 public final int OFFSET_NUM_COLS;
77 public final int OFFSET_NUM_INDEX_SLOTS;
78 public final int OFFSET_NUM_INDEXES;
79 public final int OFFSET_OWNED_PAGES;
80 public final int OFFSET_FREE_SPACE_PAGES;
81 public final int OFFSET_INDEX_DEF_BLOCK;
82
83 public final int OFFSET_INDEX_NUMBER_BLOCK;
84
85 public final int OFFSET_COLUMN_TYPE;
86 public final int OFFSET_COLUMN_NUMBER;
87 public final int OFFSET_COLUMN_PRECISION;
88 public final int OFFSET_COLUMN_SCALE;
89 public final int OFFSET_COLUMN_FLAGS;
90 public final int OFFSET_COLUMN_COMPRESSED_UNICODE;
91 public final int OFFSET_COLUMN_LENGTH;
92 public final int OFFSET_COLUMN_VARIABLE_TABLE_INDEX;
93 public final int OFFSET_COLUMN_FIXED_DATA_OFFSET;
94
95 public final int OFFSET_TABLE_DEF_LOCATION;
96
97 public final int OFFSET_ROW_START;
98 public final int OFFSET_USAGE_MAP_START;
99
100 public final int OFFSET_USAGE_MAP_PAGE_DATA;
101
102 public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
103
104 public final int OFFSET_FREE_SPACE;
105 public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
106 public final int MAX_NUM_ROWS_ON_DATA_PAGE;
107
108 public final int OFFSET_INDEX_COMPRESSED_BYTE_COUNT;
109 public final int OFFSET_INDEX_ENTRY_MASK;
110 public final int OFFSET_PREV_INDEX_PAGE;
111 public final int OFFSET_NEXT_INDEX_PAGE;
112 public final int OFFSET_CHILD_TAIL_INDEX_PAGE;
113
114 public final int SIZE_INDEX_DEFINITION;
115 public final int SIZE_COLUMN_HEADER;
116 public final int SIZE_ROW_LOCATION;
117 public final int SIZE_LONG_VALUE_DEF;
118 public final int MAX_INLINE_LONG_VALUE_SIZE;
119 public final int MAX_LONG_VALUE_ROW_SIZE;
120 public final int SIZE_TDEF_HEADER;
121 public final int SIZE_TDEF_TRAILER;
122 public final int SIZE_COLUMN_DEF_BLOCK;
123 public final int SIZE_INDEX_ENTRY_MASK;
124
125 public final int USAGE_MAP_TABLE_BYTE_LENGTH;
126
127 public final Charset CHARSET;
128
129 public static final JetFormat VERSION_4 = new Jet4Format();
130
131
132
133
134 public static JetFormat getFormat(FileChannel channel) throws IOException {
135 ByteBuffer buffer = ByteBuffer.allocate(1);
136 int bytesRead = channel.read(buffer, OFFSET_VERSION);
137 if(bytesRead < 1) {
138 throw new IOException("Empty database file");
139 }
140 buffer.flip();
141 byte version = buffer.get();
142 if (version == CODE_VERSION_4) {
143 return VERSION_4;
144 }
145 throw new IOException("Unsupported version: " + version);
146 }
147
148 private JetFormat(String name) {
149 _name = name;
150
151 PAGE_SIZE = definePageSize();
152 MAX_DATABASE_SIZE = defineMaxDatabaseSize();
153
154 MAX_ROW_SIZE = defineMaxRowSize();
155 PAGE_INITIAL_FREE_SPACE = definePageInitialFreeSpace();
156
157 OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
158 OFFSET_NUM_ROWS = defineOffsetNumRows();
159 OFFSET_NEXT_AUTO_NUMBER = defineOffsetNextAutoNumber();
160 OFFSET_TABLE_TYPE = defineOffsetTableType();
161 OFFSET_MAX_COLS = defineOffsetMaxCols();
162 OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
163 OFFSET_NUM_COLS = defineOffsetNumCols();
164 OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
165 OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
166 OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
167 OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
168 OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
169
170 OFFSET_INDEX_NUMBER_BLOCK = defineOffsetIndexNumberBlock();
171
172 OFFSET_COLUMN_TYPE = defineOffsetColumnType();
173 OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
174 OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
175 OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
176 OFFSET_COLUMN_FLAGS = defineOffsetColumnFlags();
177 OFFSET_COLUMN_COMPRESSED_UNICODE = defineOffsetColumnCompressedUnicode();
178 OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
179 OFFSET_COLUMN_VARIABLE_TABLE_INDEX = defineOffsetColumnVariableTableIndex();
180 OFFSET_COLUMN_FIXED_DATA_OFFSET = defineOffsetColumnFixedDataOffset();
181
182 OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
183
184 OFFSET_ROW_START = defineOffsetRowStart();
185 OFFSET_USAGE_MAP_START = defineOffsetUsageMapStart();
186
187 OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
188
189 OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
190
191 OFFSET_FREE_SPACE = defineOffsetFreeSpace();
192 OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
193 MAX_NUM_ROWS_ON_DATA_PAGE = defineMaxNumRowsOnDataPage();
194
195 OFFSET_INDEX_COMPRESSED_BYTE_COUNT = defineOffsetIndexCompressedByteCount();
196 OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
197 OFFSET_PREV_INDEX_PAGE = defineOffsetPrevIndexPage();
198 OFFSET_NEXT_INDEX_PAGE = defineOffsetNextIndexPage();
199 OFFSET_CHILD_TAIL_INDEX_PAGE = defineOffsetChildTailIndexPage();
200
201 SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
202 SIZE_COLUMN_HEADER = defineSizeColumnHeader();
203 SIZE_ROW_LOCATION = defineSizeRowLocation();
204 SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
205 MAX_INLINE_LONG_VALUE_SIZE = defineMaxInlineLongValueSize();
206 MAX_LONG_VALUE_ROW_SIZE = defineMaxLongValueRowSize();
207 SIZE_TDEF_HEADER = defineSizeTdefHeader();
208 SIZE_TDEF_TRAILER = defineSizeTdefTrailer();
209 SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
210 SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
211
212 USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
213
214 CHARSET = defineCharset();
215 }
216
217 protected abstract int definePageSize();
218 protected abstract long defineMaxDatabaseSize();
219
220 protected abstract int defineMaxRowSize();
221 protected abstract int definePageInitialFreeSpace();
222
223 protected abstract int defineOffsetNextTableDefPage();
224 protected abstract int defineOffsetNumRows();
225 protected abstract int defineOffsetNextAutoNumber();
226 protected abstract int defineOffsetTableType();
227 protected abstract int defineOffsetMaxCols();
228 protected abstract int defineOffsetNumVarCols();
229 protected abstract int defineOffsetNumCols();
230 protected abstract int defineOffsetNumIndexSlots();
231 protected abstract int defineOffsetNumIndexes();
232 protected abstract int defineOffsetOwnedPages();
233 protected abstract int defineOffsetFreeSpacePages();
234 protected abstract int defineOffsetIndexDefBlock();
235
236 protected abstract int defineOffsetIndexNumberBlock();
237
238 protected abstract int defineOffsetColumnType();
239 protected abstract int defineOffsetColumnNumber();
240 protected abstract int defineOffsetColumnPrecision();
241 protected abstract int defineOffsetColumnScale();
242 protected abstract int defineOffsetColumnFlags();
243 protected abstract int defineOffsetColumnCompressedUnicode();
244 protected abstract int defineOffsetColumnLength();
245 protected abstract int defineOffsetColumnVariableTableIndex();
246 protected abstract int defineOffsetColumnFixedDataOffset();
247
248 protected abstract int defineOffsetTableDefLocation();
249
250 protected abstract int defineOffsetRowStart();
251 protected abstract int defineOffsetUsageMapStart();
252
253 protected abstract int defineOffsetUsageMapPageData();
254
255 protected abstract int defineOffsetReferenceMapPageNumbers();
256
257 protected abstract int defineOffsetFreeSpace();
258 protected abstract int defineOffsetNumRowsOnDataPage();
259 protected abstract int defineMaxNumRowsOnDataPage();
260
261 protected abstract int defineOffsetIndexCompressedByteCount();
262 protected abstract int defineOffsetIndexEntryMask();
263 protected abstract int defineOffsetPrevIndexPage();
264 protected abstract int defineOffsetNextIndexPage();
265 protected abstract int defineOffsetChildTailIndexPage();
266
267 protected abstract int defineSizeIndexDefinition();
268 protected abstract int defineSizeColumnHeader();
269 protected abstract int defineSizeRowLocation();
270 protected abstract int defineSizeLongValueDef();
271 protected abstract int defineMaxInlineLongValueSize();
272 protected abstract int defineMaxLongValueRowSize();
273 protected abstract int defineSizeTdefHeader();
274 protected abstract int defineSizeTdefTrailer();
275 protected abstract int defineSizeColumnDefBlock();
276 protected abstract int defineSizeIndexEntryMask();
277
278 protected abstract int defineUsageMapTableByteLength();
279
280 protected abstract Charset defineCharset();
281
282 @Override
283 public String toString() {
284 return _name;
285 }
286
287 private static final class Jet4Format extends JetFormat {
288
289 private Jet4Format() {
290 super("VERSION_4");
291 }
292
293 @Override
294 protected int definePageSize() { return 4096; }
295
296 @Override
297 protected long defineMaxDatabaseSize() {
298 return (2L * 1024L * 1024L * 1024L);
299 }
300
301 @Override
302 protected int defineMaxRowSize() { return 4060; }
303 @Override
304 protected int definePageInitialFreeSpace() { return PAGE_SIZE - 14; }
305
306 @Override
307 protected int defineOffsetNextTableDefPage() { return 4; }
308 @Override
309 protected int defineOffsetNumRows() { return 16; }
310 @Override
311 protected int defineOffsetNextAutoNumber() { return 20; }
312 @Override
313 protected int defineOffsetTableType() { return 40; }
314 @Override
315 protected int defineOffsetMaxCols() { return 41; }
316 @Override
317 protected int defineOffsetNumVarCols() { return 43; }
318 @Override
319 protected int defineOffsetNumCols() { return 45; }
320 @Override
321 protected int defineOffsetNumIndexSlots() { return 47; }
322 @Override
323 protected int defineOffsetNumIndexes() { return 51; }
324 @Override
325 protected int defineOffsetOwnedPages() { return 55; }
326 @Override
327 protected int defineOffsetFreeSpacePages() { return 59; }
328 @Override
329 protected int defineOffsetIndexDefBlock() { return 63; }
330
331 @Override
332 protected int defineOffsetIndexNumberBlock() { return 52; }
333
334 @Override
335 protected int defineOffsetColumnType() { return 0; }
336 @Override
337 protected int defineOffsetColumnNumber() { return 5; }
338 @Override
339 protected int defineOffsetColumnPrecision() { return 11; }
340 @Override
341 protected int defineOffsetColumnScale() { return 12; }
342 @Override
343 protected int defineOffsetColumnFlags() { return 15; }
344 @Override
345 protected int defineOffsetColumnCompressedUnicode() { return 16; }
346 @Override
347 protected int defineOffsetColumnLength() { return 23; }
348 @Override
349 protected int defineOffsetColumnVariableTableIndex() { return 7; }
350 @Override
351 protected int defineOffsetColumnFixedDataOffset() { return 21; }
352
353 @Override
354 protected int defineOffsetTableDefLocation() { return 4; }
355
356 @Override
357 protected int defineOffsetRowStart() { return 14; }
358 @Override
359 protected int defineOffsetUsageMapStart() { return 5; }
360
361 @Override
362 protected int defineOffsetUsageMapPageData() { return 4; }
363
364 @Override
365 protected int defineOffsetReferenceMapPageNumbers() { return 1; }
366
367 @Override
368 protected int defineOffsetFreeSpace() { return 2; }
369 @Override
370 protected int defineOffsetNumRowsOnDataPage() { return 12; }
371 @Override
372 protected int defineMaxNumRowsOnDataPage() { return 255; }
373
374 @Override
375 protected int defineOffsetIndexCompressedByteCount() { return 24; }
376 @Override
377 protected int defineOffsetIndexEntryMask() { return 27; }
378 @Override
379 protected int defineOffsetPrevIndexPage() { return 12; }
380 @Override
381 protected int defineOffsetNextIndexPage() { return 16; }
382 @Override
383 protected int defineOffsetChildTailIndexPage() { return 20; }
384
385 @Override
386 protected int defineSizeIndexDefinition() { return 12; }
387 @Override
388 protected int defineSizeColumnHeader() { return 25; }
389 @Override
390 protected int defineSizeRowLocation() { return 2; }
391 @Override
392 protected int defineSizeLongValueDef() { return 12; }
393 @Override
394 protected int defineMaxInlineLongValueSize() { return 64; }
395 @Override
396 protected int defineMaxLongValueRowSize() { return 4076; }
397 @Override
398 protected int defineSizeTdefHeader() { return 63; }
399 @Override
400 protected int defineSizeTdefTrailer() { return 2; }
401 @Override
402 protected int defineSizeColumnDefBlock() { return 25; }
403 @Override
404 protected int defineSizeIndexEntryMask() { return 453; }
405
406 @Override
407 protected int defineUsageMapTableByteLength() { return 64; }
408
409 @Override
410 protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
411 }
412
413 }