Browse Source

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
tags/jackcess-2.2.1
James Ahlborn 5 years ago
parent
commit
112cb827e9

+ 5
- 0
NOTICE.txt View File

@@ -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.

+ 20
- 2
src/changes/changes.xml View File

@@ -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"

+ 1
- 1
src/main/java/com/healthmarketscience/jackcess/expr/package-info.java View File

@@ -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>

+ 6
- 0
src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java View File

@@ -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);


+ 13
- 3
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java View File

@@ -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_
*/

+ 4
- 4
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java View File

@@ -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();

+ 22
- 17
src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java View File

@@ -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);
}

+ 7
- 2
src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java View File

@@ -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();
}
};


+ 8
- 6
src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java View File

@@ -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);
}
}
}

Loading…
Cancel
Save