APIdia Launch Partner
Top Description Inners Fields Constructors Methods
io.github.spannm.jackcess.impl

public final Class IndexData

extends Object
Class Inheritance
Static Imports
io.github.spannm.jackcess.impl.IndexCodes.ASC_BOOLEAN_FALSE, .IndexCodes.ASC_BOOLEAN_TRUE, .IndexCodes.DESC_BOOLEAN_FALSE, .IndexCodes.DESC_BOOLEAN_TRUE, .IndexCodes.getNullEntryFlag, .IndexCodes.getStartEntryFlag

Low-level representation of an MS Access table index.

This is the physical index data stored on disk, which may back one or more logical io.github.spannm.jackcess.Index objects (e.g. a unique index and a foreign-key reference can share the same underlying data pages).

Index entry encoding

Each row value that participates in an index is encoded into a compact, order-preserving byte sequence (an index entry). The encoding is type-specific and is handled by inner ColumnDescriptor subclasses:

Ascending vs. descending columns

For descending index columns all bytes written by a ColumnDescriptor are XOR-flipped (0xFF) after encoding, so that a byte-wise ascending comparison of the raw entry bytes still yields the correct descending order.

Index page structure

Index entries are stored in a B-tree of index data pages managed by IndexPageCache. Leaf pages hold the actual encoded entries together with their RowIdImpl; intermediate pages hold separator entries pointing to child pages. Pages are read lazily (on first access) and written back via update().
Author
Tim McCune
See Also
ColumnImpl.SortOrder, GeneralLegacyIndexCodes, GeneralIndexCodes, General97IndexCodes

Nested and Inner Type Summary

Modifier and TypeClass and Description
private class
IndexData.AddRowPendingChange

PendingChange for a row addition.

private static class
IndexData.BinaryColumnDescriptor

ColumnDescriptor for BINARY columns.

private static class
IndexData.BooleanColumnDescriptor

ColumnDescriptor for boolean columns.

private static class
IndexData.ByteColumnDescriptor

ColumnDescriptor for byte based columns.

public abstract static class
IndexData.ColumnDescriptor

Encodes column values into the byte sequences that make up an index entry.

protected abstract static class
IndexData.DataPage

Object used to maintain state about an Index page.

public static class
IndexData.Entry

A single leaf entry in an index (points to a single row)

public class
IndexData.EntryCursor

Utility class to traverse the entries in the Index.

public static enum
IndexData.EntryType

type attributes for Entries which simplify comparisons

private static class
IndexData.ExtDateColumnDescriptor

ColumnDescriptor for extended date/time based columns.

private static class
IndexData.FixedPointColumnDescriptor

ColumnDescriptor for new-style fixed point based columns.

private static class
IndexData.FloatingPointColumnDescriptor

ColumnDescriptor for floating point based columns.

private static class
IndexData.Gen97TextColumnDescriptor

ColumnDescriptor for text columns using the General 97 sort order (Access 97; LCID 1033, version −1).

private static class
IndexData.GenLegTextColumnDescriptor

ColumnDescriptor for text columns using the General Legacy sort order (Access 2000–2007; LCID 1033, version 0).

private static class
IndexData.GenTextColumnDescriptor

ColumnDescriptor for text columns using the General sort order (Access 2010+; LCID 1033, version 1).

private static class
IndexData.GuidColumnDescriptor

ColumnDescriptor for guid columns.

private static enum
IndexData.IndexStatus

support status for an index

private static class
IndexData.IntegerColumnDescriptor

ColumnDescriptor for integer based columns.

private static class
IndexData.LegacyFixedPointColumnDescriptor

ColumnDescriptor for fixed point based columns (legacy sort order).

private static class
IndexData.NodeEntry

A single node entry in an index (points to a sub-page in the index)

public abstract static class
IndexData.PendingChange

Utility class which maintains information about a pending index update.

private static class
IndexData.Position

Simple value object for maintaining some cursor state.

private class
IndexData.ReadOnlyColumnDescriptor

Sentinel ColumnDescriptor used when Jackcess cannot encode values for a particular column in an index.

private static class
IndexData.RootDataPage

Simple implementation of a DataPage

private static class
IndexData.RussianTextColumnDescriptor

ColumnDescriptor for text columns using the Russian/Cyrillic sort order (LCID 1049, version 0).

private static class
IndexData.TurkishTextColumnDescriptor

ColumnDescriptor for text columns using the Turkish sort order (LCID 1055, version 0).

private static class
IndexData.UkrainianTextColumnDescriptor

ColumnDescriptor for text columns using the Ukrainian/Cyrillic sort order (LCID 1058, version 0).

private class
IndexData.UpdateRowPendingChange

PendingChange for a row update (which is essentially a deletion followed by an addition).

Field Summary

Modifier and TypeField and Description
private static final byte[]
public static final byte
public static final Comparator<byte[]>
pack-priv static final short
private final List<IndexData.ColumnDescriptor>
columns

List of columns and flags

private static final byte
COMPLEX_INDEX_MARKER

the byte after the index flags, for an index over a complex column.

private static final byte[]
pack-priv static final byte[]
private static final ByteOrder
private ByteUtil.ByteStream
entryBuffer

temp buffer used to create index entries

public static final IndexData.Entry
FIRST_ENTRY

special entry which is less than any other entry

public static final byte
private final TempBufferHolder
indexBufferH

temp buffer used to read/write the index pages

private final List<Index>
indexes

the logical indexes which this index data backs

private byte
indexFlags

flags for this index

private boolean
initialized

true if the index entries have been initialized, false otherwise

pack-priv static final int
private static final int
KEPT_KEY_LENGTH

number of leading key bytes a truncated key keeps verbatim

private static final int
KEY_DIGEST_LENGTH

length of the digest which ends a truncated key

private static final int
KEY_DIGEST_POLY

polynomial behind KEY_DIGEST_TABLE, the CRC-16/ARC polynomial in its MSB-first form

private static final int[]
public static final IndexData.Entry
LAST_ENTRY

special entry which is greater than any other entry

pack-priv static final Logger
private static final int
public static final int
MAX_COLUMNS

Max number of columns in an index

private static final int
MAX_KEY_LENGTH

maximum length of the key portion of an index entry.

public static final Object
MAX_VALUE

special object which will always be greater than any other value, when searching for an index entry range in a multi-value index

private final int
maxPageEntrySize

max size for all the entries written to a given index data page

public static final Object
MIN_VALUE

special object which will always be greater than any other value, when searching for an index entry range in a multi-value index

private int
modCount

modification count for the table, keeps cursors up-to-date

private String
name

name, generated on demand

private static final IndexData.DataPage
private final int
number

0-based index data number

private UsageMap
ownedPages

Usage map of pages that this index owns

private final IndexPageCache
pageCache

Cache which manages the index pages

private boolean
primaryKey

whether or not this index data is backing a primary key logical index

public static final byte
private int
rootPageNumber

Page number of the root index data

private IndexData.IndexStatus
status

current support status of this index

private final TableImpl
table

owning table

public static final byte
private int
uniqueEntryCount

The number of unique entries which have been added to this index.

private final int
uniqueEntryCountOffset

offset within the tableDefinition buffer of the uniqueEntryCount for this index

public static final byte
private String
unsupportedReason

if non-null, the reason why this index has a non-IndexStatus#VALID status

Constructor Summary

AccessConstructor and Description
pack-priv
IndexData(TableImpl table, int number, int uniqueEntryCount, int uniqueEntryCountOffset)

Method Summary

Modifier and TypeMethod and Description
pack-priv void
addIndex(Index index)

Adds a logical index which this data is backing.

pack-priv void
addOwnedPage(int pageNumber)

private static int
calcMaxPageEntrySize(JetFormat format)

Returns the maximum amount of entry data which can be encoded on any index page.

pack-priv void
public static void
public Object[]

Returns:

the appropriate sparse array of data or null if not all columns for this index were provided
constructIndexRow
(String colName, Object value)

Constructs an array of values appropriate for this index from the given column value.

public Object[]

Returns:

the appropriate sparse array of data or null if not all columns for this index were provided
constructIndexRow
(Map<String, ?> row)

Constructs an array of values appropriate for this index from the given column values.

public Object[]

Returns:

the appropriate sparse array of data
constructIndexRowFromEntry
(Object... values)

Constructs an array of values appropriate for this index from the given column values, expected to match the columns for this index.

public Object[]

Returns:

the appropriate sparse array of data or null if no prefix list of columns for this index were provided
constructPartialIndexRow
(Object filler, String colName, Object value)

Constructs an array of values appropriate for this index from the given column value, which must be the first column of the index.

public Object[]

Returns:

the appropriate sparse array of data or null if no prefix list of columns for this index were provided
constructPartialIndexRow
(Object filler, Map<String, ?> row)

Constructs an array of values appropriate for this index from the given column values, possibly only using a subset of the given values.

public Object[]

Returns:

the appropriate sparse array of data
constructPartialIndexRowFromEntry
(Object filler, Object... values)

Constructs an array of values appropriate for this index from the given column values, possibly only providing a prefix subset of the index columns (at least one value must be provided).

private int
countNullValues(Object[] values)

Determines the number of null values for this index from the given row.

public static IndexData
create(TableImpl table, ByteBuffer tableBuffer, int number, JetFormat format)

Creates an IndexData appropriate for the given table, using information from the given table definition buffer.

private byte[]
createEntryBytes(Object[] values)

Creates the entry bytes for a row of values.

private static int[]
createKeyDigestTable()

Builds the transition table for the truncated key digest.

private static ByteBuffer
private static IndexData.Entry
createSpecialEntry(RowIdImpl rowId)

Creates one of the special index entries.

public IndexData.EntryCursor
cursor()

Gets a new cursor for this index.

public IndexData.EntryCursor
cursor(Object[]
the first row of data for the cursor, or null for the first entry
startRow
,
boolean
whether or not startRow is inclusive or exclusive
startInclusive
,
Object[]
the last row of data for the cursor, or null for the last entry
endRow
,
boolean
whether or not endRow is inclusive or exclusive
endInclusive
)

Gets a new cursor for this index, narrowed to the range defined by the given startRow and endRow.

public void
deleteRow(Object[]
Row to remove
row
,
RowIdImpl
rowId of the row to be removed
rowId
)

Removes a row from this index

Forces index initialization.

private IndexData.Entry
private static byte[]
encodeNumberColumnValue(Object value, ColumnImpl column)

Writes the value of the given column type to a byte array and returns it.

pack-priv IndexData.DataPage
findDataPage(IndexData.Entry entry)

Finds the data page for the given entry.

private IndexData.Position
private static byte[]
flipBytes(byte[] value)

Flips all the bits in the byte array.

pack-priv static byte[]
flipBytes(byte[] value, int offset, int length)

Flips the bits in the specified bytes in the byte array.

private static byte[]
flipFirstBitInByte(byte[] value, int index)

Flips the first bit in the byte at the given index.

public int
public List<IndexData.ColumnDescriptor>
getColumns()

Returns the Columns for this index (unmodifiable)

pack-priv IndexData.DataPage
getDataPage(int pageNumber)

Gets the data page for the pageNumber.

public int
getEntryCount()

Returns the number of index entries in the index.

public JetFormat
public int
public List<Index>

Returns:

All of the Indexes backed by this data (unmodifiable List)
getIndexes
()

Returns all of the Indexes backed by this data (unmodifiable List).

public byte
pack-priv int
public String
private IndexData.Position
public int
getOwnedPageCount()

Returns the number of database pages owned by this index data.

public PageChannel
private IndexData.Position
getPreviousPosition(IndexData.Position curPos)

Returns the Position before the given one, or null if none.

public Index

Returns:

the "main" logical index which is backed by this data.
getPrimaryIndex
()

Returns the "main" logical index which is backed by this data.

pack-priv int
public TableImpl
private ByteBuffer
getTempEntryBuffer(ByteBuffer indexPage, int entryLen, byte[] valuePrefix, TempBufferHolder tmpEntryBufferH)

Returns an entry buffer containing the relevant data for an entry given the valuePrefix.

public int
public int
pack-priv String

Returns:

unsupported reason string, or null if the index is fully valid
getUnsupportedReason
()

Returns the reason why this index is not fully valid, or null if the index is fully writable and usable for lookups.

public void
initialize()

Forces initialization of this index (actual parsing of index pages).

pack-priv boolean
public boolean
isInitialized()

Whether or not the complete index state has been read.

private boolean
isLeafPage(ByteBuffer buffer)

Determines if the given index page is a leaf or node page.

pack-priv boolean
isReadOnly()

Returns true if write operations are disabled entirely for this index.

public boolean
isRequired()

Whether or not values are required in the columns.

public boolean
isUnique()

Whether or not index entries must be unique.

pack-priv boolean
isValid()

Returns true if this index is fully functional for both reads and writes.

pack-priv static int
missingIndexToInsertionPoint(int idx)

Returns the valid insertion point for an index indicating a missing entry.

private IndexData.ColumnDescriptor

Returns:

a ColumnDescriptor that can encode values of the given column for index entries
newColumnDescriptor
(ColumnImpl
the table column for which to create the descriptor
col
,
byte
raw index column flags (e.g. ASCENDING_COLUMN_FLAG)
flags
)

Constructs the appropriate ColumnDescriptor for the given column and index flags.

private static IndexData.Entry
newEntry(ByteBuffer buffer, int entryLength, boolean isLeaf)

Returns a new Entry of the correct type for the given data and page type.

private IndexData.PendingChange
prepareAddEntry(IndexData.Entry newEntry, boolean isNullEntry, Object[] row, IndexData.AddRowPendingChange change)

Adds an entry to the correct index dataPage, maintaining the order.

public IndexData.PendingChange

Returns:

a PendingChange which can complete the addition or roll it back
prepareAddRow
(Object[]
Row to add
row
,
RowIdImpl
rowId of the row to be added
rowId
,
IndexData.PendingChange nextChange)

Prepares to add a row to this index.

private IndexData.PendingChange
public IndexData.PendingChange

Returns:

a PendingChange which can complete the update or roll it back
prepareUpdateRow
(Object[]
Row to be removed
oldRow
,
RowIdImpl
rowId of the row to be updated
rowId
,
Object[]
Row to be added
newRow
,
IndexData.PendingChange nextChange)

Prepares to update a row in this index.

public void
read(ByteBuffer
table definition buffer to read from initial info
tableBuffer
,
List<ColumnImpl>
Columns that this index may use
availableColumns
)

Read the rest of the index info from a tableBuffer

pack-priv void
readDataPage(IndexData.DataPage dataPage)

Reads an index page, populating the correct collection based on the page type (node or leaf).

private static int

Returns:

the level of the page in the index tree
readLevel
(ByteBuffer
the index page
buffer
,
JetFormat
format of the database
format
)

Reads the level of an index page, 0 if the format does not record one.

private IndexData.Entry
removeEntry(IndexData.Entry oldEntry)

Removes an entry from the relevant index dataPage, maintaining the order.

public static void
private void
setUnsupportedReason(String
human-readable description of why the index cannot be written; will be enriched with database/table/index context via withErrorContext(String)
reason
,
IndexData.IndexStatus
the resulting support status; either IndexStatus#BROKEN_WRITE (writes still allowed but the index is unsuitable for lookups) or IndexStatus#READ_ONLY (writes disabled entirely)
newStatus
,
ColumnImpl
the column whose descriptor triggered the unsupported condition
col
)

Marks this index as unsupported for write operations due to a feature that Jackcess cannot (yet) encode.

public boolean
shouldIgnoreNulls()

Whether or not null values are actually recorded in the index.

public String
toString()

Overrides java.lang.Object.toString.

Returns a string representation of the object.

pack-priv static byte[]
truncateEntryBytes(byte[] entryBytes)

Truncates the given entry bytes if they exceed the maximum key length, replacing the discarded bytes with a digest of them.

public void
update()

Writes the current index state to the database.

public void
validate(boolean
if false only validate currently loaded index data pages, otherwise, load and validate all index pages
forceLoad
)

Used by unit tests to validate the internal status of the index.

pack-priv String
private static String
withErrorContext(String msg, DatabaseImpl db, String tableName, String idxName)

pack-priv void
writeDataPage(IndexData.DataPage dataPage)

Write the given index page out to a buffer

pack-priv static void
writeDataPage(ByteBuffer buffer, IndexData.DataPage dataPage, int tdefPageNumber, JetFormat format)

Writes the data page info to the given buffer.

pack-priv static void
writeDefinition(TableMutator
description of the indexes to write
creator
,
ByteBuffer
Buffer to write to
buffer
,
TableMutator.IndexDataState idxDataState, ByteBuffer rootPageBuffer)

Writes the index definitions into a table definition buffer.

pack-priv static void
writeDefinitions(TableCreator
description of the indexes to write
creator
,
ByteBuffer
Buffer to write to
buffer
)

Writes the index definitions into a table definition buffer.

private static void
writeGeneralBinaryEntry(byte[] valueBytes, boolean isAsc, ByteUtil.ByteStream bout)

Writes a binary value using the general binary entry encoding rules.

pack-priv static void
writeRowCountDefinitions(TableCreator
description of the indexes to write
creator
,
ByteBuffer
Buffer to write to
buffer
)

Writes the index row count definitions into a table definition buffer.

pack-priv static void
writeRowCountDefinitions(TableMutator
description of the indexes to write
creator
,
ByteBuffer
Buffer to write to
buffer
,
int
num indexes to write
idxCount
)

Writes the index row count definitions into a table definition buffer.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAllwaitwaitwait