summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2011-04-05 04:31:16 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2011-04-05 04:31:16 +0000
commite6f3acefd378d699fb4188226f0e722c235f3942 (patch)
treee2116c8d59137d14ca1dbbcafb12fcaae3902d41
parentba660e5bcc2b8f0adaf113fcc8fab40e1dead95f (diff)
downloadjackcess-e6f3acefd378d699fb4188226f0e722c235f3942.tar.gz
jackcess-e6f3acefd378d699fb4188226f0e722c235f3942.zip
handle different versions of general sort order correctly
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@546 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/java/com/healthmarketscience/jackcess/Column.java122
-rw-r--r--src/java/com/healthmarketscience/jackcess/Database.java7
-rw-r--r--src/java/com/healthmarketscience/jackcess/IndexData.java16
-rw-r--r--src/java/com/healthmarketscience/jackcess/JetFormat.java22
-rw-r--r--test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java3
5 files changed, 132 insertions, 38 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java
index bb0ffd4..420c581 100644
--- a/src/java/com/healthmarketscience/jackcess/Column.java
+++ b/src/java/com/healthmarketscience/jackcess/Column.java
@@ -129,8 +129,16 @@ public class Column implements Comparable<Column> {
// 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 '}') */
@@ -169,7 +177,7 @@ public class Column implements Comparable<Column> {
/** 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 */
@@ -215,12 +223,8 @@ public class Column implements Comparable<Column> {
_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);
@@ -355,11 +359,11 @@ public class Column implements Comparable<Column> {
_scale = newScale;
}
- public short getTextSortOrder() {
+ public SortOrder getTextSortOrder() {
return _textSortOrder;
}
- public void setTextSortOrder(short newTextSortOrder) {
+ public void setTextSortOrder(SortOrder newTextSortOrder) {
_textSortOrder = newTextSortOrder;
}
@@ -1679,16 +1683,19 @@ public class Column implements Comparable<Column> {
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);
@@ -1734,6 +1741,43 @@ public class Column implements Comparable<Column> {
}
/**
+ * 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).
*/
@@ -1877,4 +1921,44 @@ public class Column implements Comparable<Column> {
}
}
+ /**
+ * 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 + ")";
+ }
+ }
+
}
diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java
index de76b01..5c38561 100644
--- a/src/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/java/com/healthmarketscience/jackcess/Database.java
@@ -399,7 +399,7 @@ public class Database
/** timezone to use when handling dates */
private TimeZone _timeZone;
/** language sort order to be used for textual columns */
- private Short _defaultSortOrder;
+ private Column.SortOrder _defaultSortOrder;
/** the ordering used for table columns */
private Table.ColumnOrder _columnOrder;
/** cache of in-use tables */
@@ -893,11 +893,12 @@ public class Database
* @return the currently configured database default language sort order for
* textual columns
*/
- public short getDefaultSortOrder() throws IOException {
+ public Column.SortOrder getDefaultSortOrder() throws IOException {
if(_defaultSortOrder == null) {
_pageChannel.readPage(_buffer, 0);
- _defaultSortOrder = _buffer.getShort(_format.OFFSET_SORT_ORDER);
+ _defaultSortOrder = Column.readSortOrder(
+ _buffer, _format.OFFSET_SORT_ORDER, _format);
}
return _defaultSortOrder;
}
diff --git a/src/java/com/healthmarketscience/jackcess/IndexData.java b/src/java/com/healthmarketscience/jackcess/IndexData.java
index 1540be7..245bd84 100644
--- a/src/java/com/healthmarketscience/jackcess/IndexData.java
+++ b/src/java/com/healthmarketscience/jackcess/IndexData.java
@@ -1179,14 +1179,16 @@ public abstract class IndexData {
switch(col.getType()) {
case TEXT:
case MEMO:
- if(col.getTextSortOrder() != Column.GENERAL_SORT_ORDER) {
- // unsupported sort order
- setReadOnly();
- return new ReadOnlyColumnDescriptor(col, flags);
+ Column.SortOrder sortOrder = col.getTextSortOrder();
+ if(Column.GENERAL_LEGACY_SORT_ORDER.equals(sortOrder)) {
+ return new GenLegTextColumnDescriptor(col, flags);
}
- return(col.getFormat().LEGACY_TEXT_INDEXES ?
- new GenLegTextColumnDescriptor(col, flags) :
- new GenTextColumnDescriptor(col, flags));
+ if(Column.GENERAL_SORT_ORDER.equals(sortOrder)) {
+ return new GenTextColumnDescriptor(col, flags);
+ }
+ // unsupported sort order
+ setReadOnly();
+ return new ReadOnlyColumnDescriptor(col, flags);
case INT:
case LONG:
case MONEY:
diff --git a/src/java/com/healthmarketscience/jackcess/JetFormat.java b/src/java/com/healthmarketscience/jackcess/JetFormat.java
index 0ce73ee..173d96c 100644
--- a/src/java/com/healthmarketscience/jackcess/JetFormat.java
+++ b/src/java/com/healthmarketscience/jackcess/JetFormat.java
@@ -250,9 +250,9 @@ public abstract class JetFormat {
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.
@@ -377,9 +377,9 @@ public abstract class JetFormat {
MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
LEGACY_NUMERIC_INDEXES = defineLegacyNumericIndexes();
- LEGACY_TEXT_INDEXES = defineLegacyTextIndexes();
CHARSET = defineCharset();
+ DEFAULT_SORT_ORDER = defineDefaultSortOrder();
}
protected abstract boolean defineReadOnly();
@@ -472,9 +472,9 @@ public abstract class JetFormat {
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();
@@ -668,10 +668,12 @@ public abstract class JetFormat {
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()
@@ -868,10 +870,12 @@ public abstract class JetFormat {
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()
@@ -923,7 +927,9 @@ public abstract class JetFormat {
}
@Override
- protected boolean defineLegacyTextIndexes() { return false; }
+ protected Column.SortOrder defineDefaultSortOrder() {
+ return Column.GENERAL_SORT_ORDER;
+ }
@Override
protected Map<String,Database.FileFormat> getPossibleFileFormats() {
diff --git a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
index 7c1dbe3..52c7b60 100644
--- a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
+++ b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
@@ -1136,7 +1136,8 @@ public class DatabaseTest extends TestCase {
for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) {
Database db = open(testDB);
- assertEquals(Column.GENERAL_SORT_ORDER, db.getDefaultSortOrder());
+ assertEquals(db.getFormat().DEFAULT_SORT_ORDER,
+ db.getDefaultSortOrder());
db.close();
}
}