]> source.dussan.org Git - jackcess.git/commitdiff
make SimpleColumnMatcher handle a wider range of input data types by coercing them...
authorJames Ahlborn <jtahlborn@yahoo.com>
Fri, 16 Jan 2015 04:27:21 +0000 (04:27 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Fri, 16 Jan 2015 04:27:21 +0000 (04:27 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@908 f203690c-595d-4dc9-a70b-905162fa7fd2

src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnMatcher.java

index 224348a2ff29702b9cac0be5ff0bf08348caee3d..e244d31e707a8832b4d221551427d228d3b0a619 100644 (file)
@@ -825,16 +825,24 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
    */
   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<ColumnImpl> {
       } 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<ColumnImpl> {
     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).
index 95db6a9c865175bf2d75fd84bc9c5bfb539f5ec9..35ecfbd36da5dd280587dcfffa3359a3c550feb7 100644 (file)
@@ -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;
   }
+
 }