From: James Ahlborn Date: Fri, 16 Jan 2015 04:27:21 +0000 (+0000) Subject: make SimpleColumnMatcher handle a wider range of input data types by coercing them... X-Git-Tag: jackcess-2.0.9~18 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6b74a49d9b03abc9d9d8c347c6e2297266f4a378;p=jackcess.git make SimpleColumnMatcher handle a wider range of input data types by coercing them to the appropriate internal value typefg git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@908 f203690c-595d-4dc9-a70b-905162fa7fd2 --- diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java index 224348a..e244d31 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java @@ -825,16 +825,24 @@ public class ColumnImpl implements Column, Comparable { */ public double toDateDouble(Object value) { - // seems access stores dates in the local timezone. guess you just - // hope you read it in the same timezone in which it was written! - long time = ((value instanceof Date) ? - ((Date)value).getTime() : - ((value instanceof Calendar) ? - ((Calendar)value).getTimeInMillis() : - ((Number)value).longValue())); - time += getToLocalTimeZoneOffset(time); - time += MILLIS_BETWEEN_EPOCH_AND_1900; - return time / MILLISECONDS_PER_DAY; + // seems access stores dates in the local timezone. guess you just + // hope you read it in the same timezone in which it was written! + long time = toDateLong(value); + time += getToLocalTimeZoneOffset(time); + time += MILLIS_BETWEEN_EPOCH_AND_1900; + return time / MILLISECONDS_PER_DAY; + } + + /** + * @return an appropriate Date long value for the given object + */ + private static long toDateLong(Object value) + { + return ((value instanceof Date) ? + ((Date)value).getTime() : + ((value instanceof Calendar) ? + ((Calendar)value).getTimeInMillis() : + ((Number)value).longValue())); } /** @@ -1470,6 +1478,8 @@ public class ColumnImpl implements Column, Comparable { } catch(SQLException e) { throw (IOException)(new IOException(e.getMessage())).initCause(e); } + } else if(value instanceof RawData) { + return ((RawData)value).getBytes(); } ByteArrayOutputStream bout = new ByteArrayOutputStream(); @@ -1695,6 +1705,55 @@ public class ColumnImpl implements Column, Comparable { return !(value instanceof byte[]); } + /** + * Converts the given value to the "internal" representation for the given + * data type. + */ + public static Object toInternalValue(DataType dataType, Object value) + throws IOException + { + if(value != null) { + switch(dataType) { + case BOOLEAN: + return ((value instanceof Boolean) ? value : toBooleanValue(value)); + case BYTE: + return ((value instanceof Byte) ? value : toNumber(value).byteValue()); + case INT: + return ((value instanceof Short) ? value : + toNumber(value).shortValue()); + case LONG: + return ((value instanceof Integer) ? value : + toNumber(value).intValue()); + case MONEY: + return toBigDecimal(value); + case FLOAT: + return ((value instanceof Float) ? value : + toNumber(value).floatValue()); + case DOUBLE: + return ((value instanceof Double) ? value : + toNumber(value).doubleValue()); + case SHORT_DATE_TIME: + return ((value instanceof DateExt) ? value : + new Date(toDateLong(value))); + case TEXT: + case MEMO: + case GUID: + return ((value instanceof String) ? value : + toCharSequence(value).toString()); + case NUMERIC: + return toBigDecimal(value); + case COMPLEX_TYPE: + // leave alone for now? + break; + default: + // some variation of binary data + return toByteArray(value); + } + } + + return value; + } + /** * Date subclass which stashes the original date bits, in case we attempt to * re-write the value (will not lose precision). diff --git a/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnMatcher.java b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnMatcher.java index 95db6a9..35ecfbd 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnMatcher.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnMatcher.java @@ -20,11 +20,17 @@ USA package com.healthmarketscience.jackcess.util; +import java.io.IOException; + +import com.healthmarketscience.jackcess.DataType; import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.impl.ColumnImpl; import org.apache.commons.lang.ObjectUtils; /** - * Simple concrete implementation of ColumnMatcher which test for equality. + * Simple concrete implementation of ColumnMatcher which tests for equality. + * If initial comparison fails, attempts to coerce the values to a common type + * for comparison. * * @author James Ahlborn * @usage _general_class_ @@ -39,6 +45,26 @@ public class SimpleColumnMatcher implements ColumnMatcher { public boolean matches(Table table, String columnName, Object value1, Object value2) { - return ObjectUtils.equals(value1, value2); + if(ObjectUtils.equals(value1, value2)) { + return true; + } + + if((value1 != null) && (value2 != null) && + (value1.getClass() != value2.getClass())) { + + // the values aren't the same type, try coercing them to "internal" + // values and try again + DataType dataType = table.getColumn(columnName).getType(); + try { + Object internalV1 = ColumnImpl.toInternalValue(dataType, value1); + Object internalV2 = ColumnImpl.toInternalValue(dataType, value2); + + return ObjectUtils.equals(internalV1, internalV2); + } catch(IOException e) { + // ignored, just go with the original result + } + } + return false; } + }