diff options
9 files changed, 67 insertions, 16 deletions
diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..bf7ce69 --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,5 @@ +Many of the financial functions have been originally copied from the Apache +POI project (Apache Software Foundation) and the UCanAccess Project. They +have been then modified and adapted so that they are integrated with Jackcess, +in a consistent manner. The Apache POI and UCanAccess projects are licensed +under Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0. diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 74c82ad..3d1160d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -6,8 +6,26 @@ <body> <release version="2.2.1" date="TBD"> <action dev="jahlborn" type="update"> - Implement IsNumeric function. Add support for hex/oct integer - strings. + Implement the majority of the missing standard functions: + FormatCurrency, FormatDateTime, FormatNumber, FormatPercent, Val, + DateAdd, DateDiff, DatePart, MonthName, WeekdayName, DDB, IPmt, PPmt, + Rate, SLN, SYD, Format, Replace, StrConv. (Note that the internal API + for the expr package has changed in an incompatible way. However, + since the API is still experimental, this was deemed acceptable for a + minor version.). Note that many of the financial functions were + copied and adpated from the Apache POI and UCanAccess projects (which + are both under the Apache License 2.0). + </action> + <action dev="jahlborn" type="update"> + Implement more type coercion methods for expressions. Add support for + hex/oct integer strings. Add support for number strings with commas. + Add support for coercing numeric String to a date/time value. Add + support for date/time values with implicit (current) year. + </action> + <action dev="jahlborn" type="fix" system="SourceForge2" issue="150"> + Ignore column validators for read-only dbs. This will avoid + irrelevant failures when reading databases which have invalid column + properties. </action> </release> <release version="2.2.0" date="2018-09-08" diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java index 2236c1d..99b9162 100644 --- a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java +++ b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java @@ -215,7 +215,7 @@ limitations under the License. * * <table border="1" width="25%" cellpadding="3" cellspacing="0"> * <tr class="TableHeadingColor" align="left"><th>Function</th><th>Supported</th></tr> - * <tr class="TableRowColor"><td>Format[$]</td><td></td></tr> + * <tr class="TableRowColor"><td>Format[$]</td><td>Partial</td></tr> * <tr class="TableRowColor"><td>InStr</td><td>Y</td></tr> * <tr class="TableRowColor"><td>InStrRev</td><td>Y</td></tr> * <tr class="TableRowColor"><td>LCase[$]</td><td>Y</td></tr> diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java index 8e67d60..6ab88ab 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java @@ -546,6 +546,12 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext } void initColumnValidator() throws IOException { + + if(getDatabase().isReadOnly()) { + // validators are irrelevant for read-only databases + return; + } + // first initialize any "external" (user-defined) validator setColumnValidator(null); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java index c5f5481..dcd4e18 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java @@ -262,6 +262,8 @@ public class DatabaseImpl implements Database, ZoneContext private final Path _file; /** the simple name of the database */ private final String _name; + /** whether or not this db is read-only */ + private final boolean _readOnly; /** Buffer to hold database pages */ private ByteBuffer _buffer; /** ID of the Tables system object */ @@ -409,7 +411,8 @@ public class DatabaseImpl implements Database, ZoneContext } DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync, - null, charset, timeZone, provider); + null, charset, timeZone, provider, + readOnly); success = true; return db; @@ -468,7 +471,8 @@ public class DatabaseImpl implements Database, ZoneContext transferDbFrom(channel, getResourceAsStream(details.getEmptyFilePath())); channel.force(true); DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync, - fileFormat, charset, timeZone, null); + fileFormat, charset, timeZone, null, + false); success = true; return db; } finally { @@ -520,11 +524,13 @@ public class DatabaseImpl implements Database, ZoneContext */ protected DatabaseImpl(Path file, FileChannel channel, boolean closeChannel, boolean autoSync, FileFormat fileFormat, Charset charset, - TimeZone timeZone, CodecProvider provider) + TimeZone timeZone, CodecProvider provider, + boolean readOnly) throws IOException { _file = file; _name = getName(file); + _readOnly = readOnly; _format = JetFormat.getFormat(channel); _charset = ((charset == null) ? getDefaultCharset(_format) : charset); _columnOrder = getDefaultColumnOrder(); @@ -557,6 +563,10 @@ public class DatabaseImpl implements Database, ZoneContext return _name; } + public boolean isReadOnly() { + return _readOnly; + } + /** * @usage _advanced_method_ */ diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java index fcc9cb5..77edf80 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java @@ -425,7 +425,7 @@ public class DefaultTextFunctions } }); - public static final Function FORMAT = registerFunc(new FuncVar("Format", 1, 4) { + public static final Function FORMAT = registerStringFunc(new FuncVar("Format", 1, 4) { @Override protected Value evalVar(EvalContext ctx, Value[] params) { diff --git a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java index 0463b2d..1dc0b80 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java @@ -138,8 +138,11 @@ public abstract class CustomLinkResolver implements LinkResolver { Object customFile = loadCustomFile(linkerDb, linkeeFileName); if(customFile != null) { + // if linker is read-only, open linkee read-only + boolean readOnly = ((linkerDb instanceof DatabaseImpl) ? + ((DatabaseImpl)linkerDb).isReadOnly() : false); return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(), - getDefaultTempDirectory()); + getDefaultTempDirectory(), readOnly); } return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName); } @@ -159,7 +162,8 @@ public abstract class CustomLinkResolver implements LinkResolver * @return the temp db for holding the linked table info */ protected Database createTempDb(Object customFile, FileFormat format, - boolean inMemory, Path tempDir) + boolean inMemory, Path tempDir, + boolean readOnly) throws IOException { Path dbFile = null; @@ -182,7 +186,7 @@ public abstract class CustomLinkResolver implements LinkResolver TempDatabaseImpl.initDbChannel(channel, format); TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile, - channel, format); + channel, format, readOnly); success = true; return db; @@ -259,10 +263,11 @@ public abstract class CustomLinkResolver implements LinkResolver protected TempDatabaseImpl(CustomLinkResolver resolver, Object customFile, Path file, FileChannel channel, - FileFormat fileFormat) + FileFormat fileFormat, boolean readOnly) throws IOException { - super(file, channel, true, false, fileFormat, null, null, null); + super(file, channel, true, false, fileFormat, null, null, null, + readOnly); _resolver = resolver; _customFile = customFile; } diff --git a/src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java b/src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java index ebb1bbd..5310449 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java @@ -21,6 +21,7 @@ import java.io.IOException; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DatabaseBuilder; +import com.healthmarketscience.jackcess.impl.DatabaseImpl; /** * Resolver for linked databases. @@ -28,7 +29,7 @@ import com.healthmarketscience.jackcess.DatabaseBuilder; * @author James Ahlborn * @usage _intermediate_class_ */ -public interface LinkResolver +public interface LinkResolver { /** * default link resolver used if none provided @@ -39,7 +40,11 @@ public interface LinkResolver String linkeeFileName) throws IOException { - return DatabaseBuilder.open(new File(linkeeFileName)); + // if linker is read-only, open linkee read-only + boolean readOnly = ((linkerDb instanceof DatabaseImpl) ? + ((DatabaseImpl)linkerDb).isReadOnly() : false); + return new DatabaseBuilder(new File(linkeeFileName)) + .setReadOnly(readOnly).open(); } }; diff --git a/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java b/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java index b2dfc06..d0446b2 100644 --- a/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java @@ -149,11 +149,13 @@ public class CustomLinkResolverTest extends TestCase @Override protected Database createTempDb(Object customFile, FileFormat format, - boolean inMemory, Path tempDir) + boolean inMemory, Path tempDir, + boolean readOnly) throws IOException { inMemory = "testFile1.txt".equals(customFile); - return super.createTempDb(customFile, format, inMemory, tempDir); + return super.createTempDb(customFile, format, inMemory, tempDir, + readOnly); } } } |