aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2018-12-17 21:39:40 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2018-12-17 21:39:40 +0000
commit112cb827e960be047f38cd7c60b27b4202f02596 (patch)
treebe9a0f743104ac3531edea0d44380207b761f9de
parentcd6d6e622caf9957dada889def6f95e1a75f106d (diff)
downloadjackcess-112cb827e960be047f38cd7c60b27b4202f02596.tar.gz
jackcess-112cb827e960be047f38cd7c60b27b4202f02596.zip
Ignore column validators for read-only dbs. This will avoid irrelevant failures when reading databases which have invalid column properties. Fixes #150
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1240 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--NOTICE.txt5
-rw-r--r--src/changes/changes.xml22
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/expr/package-info.java2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java6
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java16
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java8
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java39
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java9
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java14
9 files changed, 86 insertions, 35 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 28d9a86..6e4d5ab 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 6d237b4..0016687 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -491,6 +491,12 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
}
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 6831e99..bb74bba 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -255,6 +255,8 @@ public class DatabaseImpl implements Database
private final File _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 */
@@ -399,7 +401,8 @@ public class DatabaseImpl implements Database
}
DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync,
- null, charset, timeZone, provider);
+ null, charset, timeZone, provider,
+ readOnly);
success = true;
return db;
@@ -458,7 +461,8 @@ public class DatabaseImpl implements Database
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 {
@@ -510,11 +514,13 @@ public class DatabaseImpl implements Database
*/
protected DatabaseImpl(File 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();
@@ -543,6 +549,10 @@ public class DatabaseImpl implements Database
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 5643766..74856aa 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) {
@@ -441,11 +441,11 @@ public class DefaultTextFunctions
String fmtStr = params[1].getAsString(ctx);
int firstDay = DefaultDateFunctions.getFirstDayParam(ctx, params, 2);
int firstWeekType = DefaultDateFunctions.getFirstWeekTypeParam(ctx, params, 3);
-
+
return FormatUtil.format(ctx, expr, fmtStr, firstDay, firstWeekType);
}
});
-
+
private static String nchars(int num, char c) {
StringBuilder sb = new StringBuilder(num);
nchars(sb, num, c);
@@ -457,7 +457,7 @@ public class DefaultTextFunctions
sb.append(c);
}
}
-
+
private static String trim(String str, boolean doLeft, boolean doRight) {
int start = 0;
int end = str.length();
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java
index 7992d71..fce5289 100644
--- a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java
+++ b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java
@@ -117,28 +117,31 @@ public abstract class CustomLinkResolver implements LinkResolver
* <pre>
* // attempt to load the linkeeFileName as a custom file
* Object customFile = loadCustomFile(linkerDb, linkeeFileName);
- *
+ *
* if(customFile != null) {
* // this is a custom file, create and return relevant temp db
* return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
* getDefaultTempDirectory());
* }
- *
+ *
* // not a custmom file, load using the default behavior
* return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName);
* </pre>
- *
+ *
* @see #loadCustomFile
* @see #createTempDb
* @see LinkResolver#DEFAULT
*/
public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName)
- throws IOException
+ throws IOException
{
Object customFile = loadCustomFile(linkerDb, linkeeFileName);
if(customFile != null) {
- return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
- getDefaultTempDirectory());
+ // if linker is read-only, open linkee read-only
+ boolean readOnly = ((linkerDb instanceof DatabaseImpl) ?
+ ((DatabaseImpl)linkerDb).isReadOnly() : false);
+ return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
+ getDefaultTempDirectory(), readOnly);
}
return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName);
}
@@ -157,8 +160,9 @@ 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, File tempDir)
+ protected Database createTempDb(Object customFile, FileFormat format,
+ boolean inMemory, File tempDir,
+ boolean readOnly)
throws IOException
{
File dbFile = null;
@@ -178,8 +182,8 @@ public abstract class CustomLinkResolver implements LinkResolver
}
TempDatabaseImpl.initDbChannel(channel, format);
- TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile,
- channel, format);
+ TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile,
+ channel, format, readOnly);
success = true;
return db;
@@ -203,7 +207,7 @@ public abstract class CustomLinkResolver implements LinkResolver
ByteUtil.closeQuietly((Closeable)customFile);
}
}
-
+
/**
* Called by {@link #resolveLinkedDatabase} to determine whether the
* linkeeFileName should be treated as a custom file (thus utiliziing a temp
@@ -252,21 +256,22 @@ public abstract class CustomLinkResolver implements LinkResolver
private final Object _customFile;
protected TempDatabaseImpl(CustomLinkResolver resolver, Object customFile,
- File file, FileChannel channel,
- FileFormat fileFormat)
+ File file, FileChannel channel,
+ 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;
}
@Override
- protected TableImpl getTable(String name, boolean includeSystemTables)
- throws IOException
+ protected TableImpl getTable(String name, boolean includeSystemTables)
+ throws IOException
{
TableImpl table = super.getTable(name, includeSystemTables);
- if((table == null) &&
+ if((table == null) &&
_resolver.loadCustomTable(this, _customFile, name)) {
table = super.getTable(name, includeSystemTables);
}
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 31a8853..87f8e6f 100644
--- a/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java
@@ -55,7 +55,7 @@ public class CustomLinkResolverTest extends TestCase
Table t1 = db.getTable("Table1");
assertNotNull(t1);
assertNotSame(db, t1.getDatabase());
-
+
assertTable(createExpectedTable(createExpectedRow("id", 0,
"data1", "row0"),
createExpectedRow("id", 1,
@@ -101,7 +101,7 @@ public class CustomLinkResolverTest extends TestCase
Database linkerDb, String linkeeFileName) throws IOException
{
return (("testFile1.txt".equals(linkeeFileName) ||
- "testFile2.txt".equals(linkeeFileName)) ?
+ "testFile2.txt".equals(linkeeFileName)) ?
linkeeFileName : null);
}
@@ -121,7 +121,7 @@ public class CustomLinkResolverTest extends TestCase
for(int i = 0; i < 3; ++i) {
t.addRow(i, "row" + i);
}
-
+
return true;
} else if("OtherTable2".equals(tableName)) {
@@ -135,7 +135,7 @@ public class CustomLinkResolverTest extends TestCase
for(int i = 3; i < 6; ++i) {
t.addRow(i, "row" + i);
}
-
+
return true;
} else if("Table4".equals(tableName)) {
@@ -149,11 +149,13 @@ public class CustomLinkResolverTest extends TestCase
@Override
protected Database createTempDb(Object customFile, FileFormat format,
- boolean inMemory, File tempDir)
+ boolean inMemory, File 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);
}
}
}