aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.txt2
-rw-r--r--src/changes/changes.xml7
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/DataType.java7
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Database.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java8
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ComplexColumnSupport.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/IndexData.java1
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java66
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java2
-rw-r--r--src/main/resources/com/healthmarketscience/jackcess/empty2016.accdbbin0 -> 364544 bytes
-rw-r--r--src/site/fml/faq.fml2
-rw-r--r--src/site/xdoc/cookbook.xml2
-rw-r--r--src/site/xdoc/index.xml2
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/BigIntTest.java102
16 files changed, 192 insertions, 19 deletions
diff --git a/README.txt b/README.txt
index 178aea2..b46c7d7 100644
--- a/README.txt
+++ b/README.txt
@@ -1,7 +1,7 @@
Jackcess
Jackcess is a pure Java library for reading from and writing to MS Access
-databases (currently supporting versions 2000-2013). It is not an
+databases (currently supporting versions 2000-2016). It is not an
application. There is no GUI. It's a library, intended for other developers to
use to build Java applications. Jackcess is licensed under the Apache License
(as of version 2.1.0).
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1825256..0ff4525 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -4,6 +4,13 @@
<author email="javajedi@users.sf.net">Tim McCune</author>
</properties>
<body>
+ <release version="2.1.10" date="TBD">
+ <action dev="jahlborn" type="update" system="SourceForge2Features"
+ issue="37">
+ Add full support for access 2016 databases including the new "Large
+ Number" (aka Bigint) data type.
+ </action>
+ </release>
<release version="2.1.9" date="2017-10-09">
<action dev="jahlborn" type="fix" system="SourceForge2" issue="141">
Handle more advanced query join constructs.
diff --git a/src/main/java/com/healthmarketscience/jackcess/DataType.java b/src/main/java/com/healthmarketscience/jackcess/DataType.java
index 5a5cebe..9baaba6 100644
--- a/src/main/java/com/healthmarketscience/jackcess/DataType.java
+++ b/src/main/java/com/healthmarketscience/jackcess/DataType.java
@@ -152,6 +152,13 @@ public enum DataType {
*/
COMPLEX_TYPE((byte) 0x12, null, 4),
/**
+ * Corresponds to a java {@link Long}. Accepts any {@link Number} (using
+ * {@link Number#longValue}), Boolean as 1 or 0, any Object converted to a
+ * String and parsed as Double, or {@code null}. Equivalent to SQL
+ * {@link Types#BIGINT}.
+ */
+ BIG_INT((byte) 0x13, null, 8),
+ /**
* Dummy type for a fixed length type which is not currently supported.
* Handled like a fixed length {@link #BINARY}.
*/
diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java
index 42eb216..5644d09 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Database.java
@@ -143,6 +143,8 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
V2007(".accdb"),
/** A database which was created by MS Access 2010+ */
V2010(".accdb"),
+ /** A database which was created by MS Access 2016+ */
+ V2016(".accdb"),
/** A database which was created by MS Money */
MSISAM(".mny");
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
index f3fdc21..e77963f 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
@@ -26,7 +26,7 @@ import java.nio.ByteOrder;
* Utility code for dealing with calculated columns.
* <p/>
* These are the currently possible calculated types: FLOAT, DOUBLE, INT,
- * LONG, GUID, SHORT_DATE_TIME, MONEY, BOOLEAN, NUMERIC, TEXT, MEMO.
+ * LONG, BIG_INT, GUID, SHORT_DATE_TIME, MONEY, BOOLEAN, NUMERIC, TEXT, MEMO.
*
* @author James Ahlborn
*/
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
index c5d0449..b5a0d0e 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -632,6 +632,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
return data;
case COMPLEX_TYPE:
return new ComplexValueForeignKeyImpl(this, buffer.getInt());
+ case BIG_INT:
+ return Long.valueOf(buffer.getLong());
default:
throw new IOException(withErrorContext("Unrecognized data type: " + _type));
}
@@ -1128,6 +1130,9 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
case COMPLEX_TYPE:
buffer.putInt(toNumber(obj).intValue());
break;
+ case BIG_INT:
+ buffer.putLong(toNumber(obj).longValue());
+ break;
case UNSUPPORTED_FIXEDLEN:
byte[] bytes = toByteArray(obj);
if(bytes.length != getLength()) {
@@ -1800,6 +1805,9 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
case COMPLEX_TYPE:
// leave alone for now?
return value;
+ case BIG_INT:
+ return ((value instanceof Long) ? value :
+ toNumber(value).longValue());
default:
// some variation of binary data
return toByteArray(value);
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ComplexColumnSupport.java b/src/main/java/com/healthmarketscience/jackcess/impl/ComplexColumnSupport.java
index 954791b..93dbf03 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ComplexColumnSupport.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ComplexColumnSupport.java
@@ -53,7 +53,8 @@ public class ComplexColumnSupport
private static final Set<DataType> MULTI_VALUE_TYPES = EnumSet.of(
DataType.BYTE, DataType.INT, DataType.LONG, DataType.FLOAT,
- DataType.DOUBLE, DataType.GUID, DataType.NUMERIC, DataType.TEXT);
+ DataType.DOUBLE, DataType.GUID, DataType.NUMERIC, DataType.TEXT,
+ DataType.BIG_INT);
/**
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 15c79e0..cc76ccb 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -116,6 +116,7 @@ public class DatabaseImpl implements Database
addFileFormatDetails(FileFormat.V2003, "empty2003", JetFormat.VERSION_4);
addFileFormatDetails(FileFormat.V2007, "empty2007", JetFormat.VERSION_12);
addFileFormatDetails(FileFormat.V2010, "empty2010", JetFormat.VERSION_14);
+ addFileFormatDetails(FileFormat.V2016, "empty2016", JetFormat.VERSION_16);
addFileFormatDetails(FileFormat.MSISAM, null, JetFormat.VERSION_MSISAM);
}
@@ -182,7 +183,7 @@ public class DatabaseImpl implements Database
private static final int DB_PARENT_ID = 0xF000000;
/** the maximum size of any of the included "empty db" resources */
- private static final long MAX_EMPTYDB_SIZE = 350000L;
+ private static final long MAX_EMPTYDB_SIZE = 370000L;
/** this object is a "system" object */
static final int SYSTEM_OBJECT_FLAG = 0x80000000;
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/IndexData.java b/src/main/java/com/healthmarketscience/jackcess/impl/IndexData.java
index e7ae7d5..e2b2dd5 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/IndexData.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/IndexData.java
@@ -1528,6 +1528,7 @@ public class IndexData {
case LONG:
case MONEY:
case COMPLEX_TYPE:
+ case BIG_INT:
return new IntegerColumnDescriptor(col, flags);
case FLOAT:
case DOUBLE:
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
index ba848e4..a230edf 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
@@ -54,10 +54,12 @@ public abstract class JetFormat {
private static final byte CODE_VERSION_3 = 0x0;
/** Version code for Jet version 4 */
private static final byte CODE_VERSION_4 = 0x1;
- /** Version code for Jet version 12 */
+ /** Version code for Jet version 12.0 */
private static final byte CODE_VERSION_12 = 0x2;
- /** Version code for Jet version 14 */
+ /** Version code for Jet version 14.0 */
private static final byte CODE_VERSION_14 = 0x3;
+ /** Version code for Jet version 16.7 */
+ private static final byte CODE_VERSION_16 = 0x5;
/** location of the engine name in the header */
static final int OFFSET_ENGINE_NAME = 0x4;
@@ -121,6 +123,9 @@ public abstract class JetFormat {
private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_14 =
Collections.singletonMap((String)null, Database.FileFormat.V2010);
+ private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_16 =
+ Collections.singletonMap((String)null, Database.FileFormat.V2016);
+
private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_MSISAM =
Collections.singletonMap((String)null, Database.FileFormat.MSISAM);
@@ -138,16 +143,24 @@ public abstract class JetFormat {
DataType.SHORT_DATE_TIME, DataType.MONEY, DataType.NUMERIC,
DataType.TEXT, DataType.MEMO);
+ /** calculated types supported in version 16 */
+ private static final Set<DataType> V16_CALC_TYPES = EnumSet.of(DataType.BIG_INT);
+ static {
+ V16_CALC_TYPES.addAll(V14_CALC_TYPES);
+ }
+
/** the JetFormat constants for the Jet database version "3" */
public static final JetFormat VERSION_3 = new Jet3Format();
/** the JetFormat constants for the Jet database version "4" */
public static final JetFormat VERSION_4 = new Jet4Format();
/** the JetFormat constants for the MSISAM database */
public static final JetFormat VERSION_MSISAM = new MSISAMFormat();
- /** the JetFormat constants for the Jet database version "12" */
+ /** the JetFormat constants for the Jet database version "12.0" */
public static final JetFormat VERSION_12 = new Jet12Format();
- /** the JetFormat constants for the Jet database version "14" */
+ /** the JetFormat constants for the Jet database version "14.0" */
public static final JetFormat VERSION_14 = new Jet14Format();
+ /** the JetFormat constants for the Jet database version "16.7" */
+ public static final JetFormat VERSION_16 = new Jet16Format();
//These constants are populated by this class's constructor. They can't be
//populated by the subclass's constructor because they are final, and Java
@@ -289,6 +302,8 @@ public abstract class JetFormat {
return VERSION_12;
} else if (version == CODE_VERSION_14) {
return VERSION_14;
+ } else if (version == CODE_VERSION_16) {
+ return VERSION_16;
}
throw new IOException("Unsupported " +
((version < CODE_VERSION_3) ? "older" : "newer") +
@@ -738,7 +753,8 @@ public abstract class JetFormat {
@Override
public boolean isSupportedDataType(DataType type) {
- return (type != DataType.COMPLEX_TYPE);
+ return ((type != DataType.COMPLEX_TYPE) &&
+ (type != DataType.BIG_INT));
}
@Override
@@ -971,7 +987,8 @@ public abstract class JetFormat {
@Override
public boolean isSupportedDataType(DataType type) {
- return (type != DataType.COMPLEX_TYPE);
+ return ((type != DataType.COMPLEX_TYPE) &&
+ (type != DataType.BIG_INT));
}
@Override
@@ -1002,7 +1019,6 @@ public abstract class JetFormat {
super("VERSION_12");
}
-
private Jet12Format(String name) {
super(name);
}
@@ -1028,7 +1044,7 @@ public abstract class JetFormat {
@Override
public boolean isSupportedDataType(DataType type) {
- return true;
+ return (type != DataType.BIG_INT);
}
@Override
@@ -1037,10 +1053,14 @@ public abstract class JetFormat {
}
}
- private static final class Jet14Format extends Jet12Format {
- private Jet14Format() {
- super("VERSION_14");
- }
+ private static class Jet14Format extends Jet12Format {
+ private Jet14Format() {
+ super("VERSION_14");
+ }
+
+ private Jet14Format(String name) {
+ super(name);
+ }
@Override
protected ColumnImpl.SortOrder defineDefaultSortOrder() {
@@ -1063,4 +1083,26 @@ public abstract class JetFormat {
}
}
+ private static final class Jet16Format extends Jet14Format {
+
+ private Jet16Format() {
+ super("VERSION_16");
+ }
+
+ @Override
+ public boolean isSupportedDataType(DataType type) {
+ return true;
+ }
+
+ @Override
+ protected Map<String,Database.FileFormat> getPossibleFileFormats() {
+ return PossibleFileFormats.POSSIBLE_VERSION_16;
+ }
+
+ @Override
+ public boolean isSupportedCalculatedDataType(DataType type) {
+ return V16_CALC_TYPES.contains(type);
+ }
+ }
+
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java
index 619da07..9ec5fca 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java
@@ -204,6 +204,8 @@ public class PropertyMapImpl implements PropertyMap
type = DataType.SHORT_DATE_TIME;
} else if(value instanceof byte[]) {
type = DataType.OLE;
+ } else if(value instanceof Long) {
+ type = DataType.BIG_INT;
} else {
throw new IllegalArgumentException(
"Could not determine type for property " + name +
diff --git a/src/main/resources/com/healthmarketscience/jackcess/empty2016.accdb b/src/main/resources/com/healthmarketscience/jackcess/empty2016.accdb
new file mode 100644
index 0000000..94f4e08
--- /dev/null
+++ b/src/main/resources/com/healthmarketscience/jackcess/empty2016.accdb
Binary files differ
diff --git a/src/site/fml/faq.fml b/src/site/fml/faq.fml
index 769936b..18bd093 100644
--- a/src/site/fml/faq.fml
+++ b/src/site/fml/faq.fml
@@ -16,7 +16,7 @@
<faq id="formats">
<question>What Access formats does it support?</question>
<answer>
- <p>Jackcess supports Access database versions 2000-2013 read/write and
+ <p>Jackcess supports Access database versions 2000-2016 read/write and
Access 97 read-only.</p>
</answer>
</faq>
diff --git a/src/site/xdoc/cookbook.xml b/src/site/xdoc/cookbook.xml
index fca2519..5e083af 100644
--- a/src/site/xdoc/cookbook.xml
+++ b/src/site/xdoc/cookbook.xml
@@ -195,7 +195,7 @@
As of version 2.1.5, Jackcess supports:
</p>
<ul>
- <li>Creating databases for Access all versions 2000-2013</li>
+ <li>Creating databases for Access all versions 2000-2016</li>
<li>Creating columns for all simple data types</li>
<li>Creating tables with single-table Indexes</li>
<li>Creating tables with (index backed) foreign-key constraints
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index bb8b877..7f23a71 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -10,7 +10,7 @@
<section name="Jackcess">
<p>
Jackcess is a pure Java library for reading from and writing to MS
- Access databases (currently supporting versions 2000-2013). It is part of the <a href="http://openhms.sourceforge.net/">OpenHMS</a> project from <a href="http://www.healthmarketscience.com/">Health Market Science, Inc.</a>. It is not an application. There is no GUI. It's a
+ Access databases (currently supporting versions 2000-2016). It is part of the <a href="http://openhms.sourceforge.net/">OpenHMS</a> project from <a href="http://www.healthmarketscience.com/">Health Market Science, Inc.</a>. It is not an application. There is no GUI. It's a
library, intended for other developers to use to build Java
applications. Jackcess is licensed under the
<a href="http://www.apache.org/licenses/LICENSE-2.0.txt">Apache License</a> (as of version 2.1.0).
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/BigIntTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/BigIntTest.java
new file mode 100644
index 0000000..143ac9b
--- /dev/null
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/BigIntTest.java
@@ -0,0 +1,102 @@
+/*
+Copyright (c) 2017 James Ahlborn
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.healthmarketscience.jackcess.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import com.healthmarketscience.jackcess.Column;
+import com.healthmarketscience.jackcess.ColumnBuilder;
+import com.healthmarketscience.jackcess.Cursor;
+import com.healthmarketscience.jackcess.CursorBuilder;
+import com.healthmarketscience.jackcess.DataType;
+import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.IndexBuilder;
+import com.healthmarketscience.jackcess.Table;
+import com.healthmarketscience.jackcess.TableBuilder;
+import junit.framework.TestCase;
+import static com.healthmarketscience.jackcess.TestUtil.*;
+import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
+
+/**
+ *
+ * @author James Ahlborn
+ */
+public class BigIntTest extends TestCase
+{
+
+ public BigIntTest(String name) throws Exception {
+ super(name);
+ }
+
+ public void testBigInt() throws Exception {
+
+ for (final Database.FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
+ JetFormat format = DatabaseImpl.getFileFormatDetails(fileFormat)
+ .getFormat();
+
+ if(!format.isSupportedDataType(DataType.BIG_INT)) {
+ continue;
+ }
+
+ Database db = create(fileFormat);
+
+ Table t = new TableBuilder("Test")
+ .addColumn(new ColumnBuilder("id", DataType.LONG)
+ .setAutoNumber(true))
+ .addColumn(new ColumnBuilder("data1", DataType.TEXT))
+ .addColumn(new ColumnBuilder("num1", DataType.BIG_INT))
+ .addIndex(new IndexBuilder("idx").addColumns("num1"))
+ .toTable(db);
+
+ long[] vals = new long[] {
+ 0L, -10L, 3844L, -45309590834L, 50392084913L, 65000L, -6489273L};
+
+ List<Map<String, Object>> expectedTable =
+ new ArrayList<Map<String, Object>>();
+
+ int idx = 1;
+ for(long lng : vals) {
+ t.addRow(Column.AUTO_NUMBER, "" + lng, lng);
+
+ expectedTable.add(createExpectedRow(
+ "id", idx++,
+ "data1", "" + lng,
+ "num1", lng));
+ }
+
+ Collections.sort(expectedTable, new Comparator<Map<String, Object>>() {
+ public int compare(
+ Map<String, Object> r1,
+ Map<String, Object> r2) {
+ Long l1 = (Long)r1.get("num1");
+ Long l2 = (Long)r2.get("num1");
+ return l1.compareTo(l2);
+ }
+ });
+
+ Cursor c = new CursorBuilder(t).setIndexByName("idx").toIndexCursor();
+
+ assertCursor(expectedTable, c);
+
+ db.close();
+ }
+ }
+}