// 0x10: replication related field (or hidden?)
// 0x80: hyperlink (some memo based thing)
- /** the "general" text sort order */
- public static final short GENERAL_SORT_ORDER = 1033;
+ /** the value for the "general" sort order */
+ private static final short GENERAL_SORT_ORDER_VALUE = 1033;
+
+ /** the "general" text sort order, legacy version (access 2000-2007) */
+ public static final SortOrder GENERAL_LEGACY_SORT_ORDER =
+ new SortOrder(GENERAL_SORT_ORDER_VALUE, (byte)0);
+
+ /** the "general" text sort order, latest version (access 2010+) */
+ public static final SortOrder GENERAL_SORT_ORDER =
+ new SortOrder(GENERAL_SORT_ORDER_VALUE, (byte)1);
/** pattern matching textual guid strings (allows for optional surrounding
'{' and '}') */
/** the index of the variable length data in the var len offset table */
private int _varLenTableIndex;
/** the collating sort order for a text field */
- private short _textSortOrder = GENERAL_SORT_ORDER;
+ private SortOrder _textSortOrder;
/** the auto number generator for this column (if autonumber column) */
private AutoNumberGenerator _autoNumberGenerator;
/** properties for this column, if any */
_scale = buffer.get(offset + getFormat().OFFSET_COLUMN_SCALE);
} else if(_type.isTextual()) {
// co-located w/ precision/scale
- _textSortOrder = buffer.getShort(
- offset + getFormat().OFFSET_COLUMN_PRECISION);
- if(_textSortOrder == 0) {
- // probably a file we wrote, before handling sort order
- _textSortOrder = GENERAL_SORT_ORDER;
- }
+ _textSortOrder = readSortOrder(
+ buffer, offset + getFormat().OFFSET_COLUMN_PRECISION, getFormat());
}
byte flags = buffer.get(offset + getFormat().OFFSET_COLUMN_FLAGS);
_variableLength = ((flags & FIXED_LEN_FLAG_MASK) == 0);
_scale = newScale;
}
- public short getTextSortOrder() {
+ public SortOrder getTextSortOrder() {
return _textSortOrder;
}
- public void setTextSortOrder(short newTextSortOrder) {
+ public void setTextSortOrder(SortOrder newTextSortOrder) {
_textSortOrder = newTextSortOrder;
}
buffer.putShort((short) 0);
}
buffer.putShort(columnNumber); //Column Number again
- if(col.getType().getHasScalePrecision()) {
- buffer.put(col.getPrecision()); // numeric precision
- buffer.put(col.getScale()); // numeric scale
- } else if(col.getType().isTextual()) {
- buffer.putShort(col.getTextSortOrder());
+ if(col.getType().isTextual()) {
+ // this will write 4 bytes
+ writeSortOrder(buffer, col._textSortOrder, format);
} else {
- buffer.put((byte) 0x00); //unused
- buffer.put((byte) 0x00); //unused
+ if(col.getType().getHasScalePrecision()) {
+ buffer.put(col.getPrecision()); // numeric precision
+ buffer.put(col.getScale()); // numeric scale
+ } else {
+ buffer.put((byte) 0x00); //unused
+ buffer.put((byte) 0x00); //unused
+ }
+ buffer.putShort((short) 0); //Unknown
}
- buffer.putShort((short) 0); //Unknown
buffer.put(getColumnBitFlags(col)); // misc col flags
if (col.isCompressedUnicode()) { //Compressed
buffer.put((byte) 1);
return flags;
}
+ /**
+ * Reads the sort order info from the given buffer from the given position.
+ */
+ static SortOrder readSortOrder(ByteBuffer buffer, int position,
+ JetFormat format)
+ {
+ short value = buffer.getShort(position);
+ byte version = buffer.get(position + 3);
+ if(value == 0) {
+ // probably a file we wrote, before handling sort order
+ return format.DEFAULT_SORT_ORDER;
+ }
+
+ if(value == GENERAL_SORT_ORDER_VALUE) {
+ if(version == GENERAL_LEGACY_SORT_ORDER.getVersion()) {
+ return GENERAL_LEGACY_SORT_ORDER;
+ }
+ if(version == GENERAL_SORT_ORDER.getVersion()) {
+ return GENERAL_SORT_ORDER;
+ }
+ }
+ return new SortOrder(value, version);
+ }
+
+ /**
+ * Writes the sort order info to the given buffer at the current position.
+ */
+ private static void writeSortOrder(ByteBuffer buffer, SortOrder sortOrder,
+ JetFormat format) {
+ if(sortOrder == null) {
+ sortOrder = format.DEFAULT_SORT_ORDER;
+ }
+ buffer.putShort(sortOrder.getValue());
+ buffer.put((byte)0x00); // unknown
+ buffer.put(sortOrder.getVersion());
+ }
+
/**
* Date subclass which stashes the original date bits, in case we attempt to
* re-write the value (will not lose precision).
}
}
+ /**
+ * Information about the sort order (collation) for a textual column.
+ */
+ public static final class SortOrder
+ {
+ private final short _value;
+ private final byte _version;
+
+ public SortOrder(short value, byte version) {
+ _value = value;
+ _version = version;
+ }
+
+ public short getValue() {
+ return _value;
+ }
+
+ public byte getVersion() {
+ return _version;
+ }
+
+ @Override
+ public int hashCode() {
+ return _value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return ((this == o) ||
+ ((o != null) && (getClass() == o.getClass()) &&
+ (_value == ((SortOrder)o)._value) &&
+ (_version == ((SortOrder)o)._version)));
+ }
+
+ @Override
+ public String toString() {
+ return _value + "(" + _version + ")";
+ }
+ }
+
}
public final int MAX_INDEX_NAME_LENGTH;
public final boolean LEGACY_NUMERIC_INDEXES;
- public final boolean LEGACY_TEXT_INDEXES;
public final Charset CHARSET;
+ public final Column.SortOrder DEFAULT_SORT_ORDER;
/**
* @param channel the database file.
MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
LEGACY_NUMERIC_INDEXES = defineLegacyNumericIndexes();
- LEGACY_TEXT_INDEXES = defineLegacyTextIndexes();
CHARSET = defineCharset();
+ DEFAULT_SORT_ORDER = defineDefaultSortOrder();
}
protected abstract boolean defineReadOnly();
protected abstract int defineMaxIndexNameLength();
protected abstract Charset defineCharset();
+ protected abstract Column.SortOrder defineDefaultSortOrder();
protected abstract boolean defineLegacyNumericIndexes();
- protected abstract boolean defineLegacyTextIndexes();
protected abstract Map<String,Database.FileFormat> getPossibleFileFormats();
protected boolean defineLegacyNumericIndexes() { return true; }
@Override
- protected boolean defineLegacyTextIndexes() { return true; }
+ protected Charset defineCharset() { return Charset.defaultCharset(); }
@Override
- protected Charset defineCharset() { return Charset.defaultCharset(); }
+ protected Column.SortOrder defineDefaultSortOrder() {
+ return Column.GENERAL_LEGACY_SORT_ORDER;
+ }
@Override
protected Map<String,Database.FileFormat> getPossibleFileFormats()
protected boolean defineLegacyNumericIndexes() { return true; }
@Override
- protected boolean defineLegacyTextIndexes() { return true; }
+ protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
@Override
- protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
+ protected Column.SortOrder defineDefaultSortOrder() {
+ return Column.GENERAL_LEGACY_SORT_ORDER;
+ }
@Override
protected Map<String,Database.FileFormat> getPossibleFileFormats()
}
@Override
- protected boolean defineLegacyTextIndexes() { return false; }
+ protected Column.SortOrder defineDefaultSortOrder() {
+ return Column.GENERAL_SORT_ORDER;
+ }
@Override
protected Map<String,Database.FileFormat> getPossibleFileFormats() {