Add TimestampType to replace DateType

patch by slebresne; reviewed by jbellis for CASSANDRA-5723


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/9ec7b808
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/9ec7b808
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/9ec7b808

Branch: refs/heads/trunk
Commit: 9ec7b808ac6786db74b5cbad0a63f6a9cdfdc5bd
Parents: e9c6742
Author: Sylvain Lebresne <sylv...@datastax.com>
Authored: Mon Jul 8 15:49:21 2013 +0200
Committer: Sylvain Lebresne <sylv...@datastax.com>
Committed: Mon Jul 8 18:55:32 2013 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 NEWS.txt                                        |   1 +
 .../org/apache/cassandra/cql3/CQL3Type.java     |   2 +-
 .../apache/cassandra/cql3/UntypedResultSet.java |   2 +-
 .../cassandra/cql3/functions/TimeuuidFcts.java  |  14 +-
 .../cassandra/db/marshal/AbstractType.java      |   1 -
 .../apache/cassandra/db/marshal/DateType.java   |  42 ++++--
 .../apache/cassandra/db/marshal/LongType.java   |   8 +-
 .../cassandra/db/marshal/TimestampType.java     | 145 +++++++++++++++++++
 .../apache/cassandra/db/marshal/UUIDType.java   |   2 +-
 .../hadoop/pig/AbstractCassandraStorage.java    |   4 +-
 .../org/apache/cassandra/tools/Shuffle.java     |   4 +-
 .../apache/cassandra/transport/DataType.java    |   5 +-
 .../apache/cassandra/type/DateSerializer.java   | 104 -------------
 .../cassandra/type/TimestampSerializer.java     | 104 +++++++++++++
 15 files changed, 304 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index eaa5eea..4b7dcc5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -72,6 +72,7 @@
  * Move resultset type information into prepare, not execute (CASSANDRA-5649)
  * Auto paging in binary protocol (CASSANDRA-4415, 5714)
  * Don't tie client side use of AbstractType to JDBC (CASSANDRA-4495)
+ * Adds new TimestampType to replace DateType (CASSANDRA-5723)
 
 
 1.2.7

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index 7e12e2c..652f8c2 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -73,6 +73,7 @@ Features
 
 1.2.7
 =====
+
 Upgrading
 ---------
     - If you have decommissioned a node in the past 72 hours, it is imperative

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/cql3/CQL3Type.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQL3Type.java 
b/src/java/org/apache/cassandra/cql3/CQL3Type.java
index d7a4e8e..aed3165 100644
--- a/src/java/org/apache/cassandra/cql3/CQL3Type.java
+++ b/src/java/org/apache/cassandra/cql3/CQL3Type.java
@@ -41,7 +41,7 @@ public interface CQL3Type
         INET     (InetAddressType.instance),
         INT      (Int32Type.instance),
         TEXT     (UTF8Type.instance),
-        TIMESTAMP(DateType.instance),
+        TIMESTAMP(TimestampType.instance),
         UUID     (UUIDType.instance),
         VARCHAR  (UTF8Type.instance),
         VARINT   (IntegerType.instance),

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/UntypedResultSet.java 
b/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
index 9bee563..25294d6 100644
--- a/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
+++ b/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
@@ -128,7 +128,7 @@ public class UntypedResultSet implements 
Iterable<UntypedResultSet.Row>
 
         public Date getTimestamp(String column)
         {
-            return DateType.instance.compose(data.get(column));
+            return TimestampType.instance.compose(data.get(column));
         }
 
         public long getLong(String column)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java 
b/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
index e325e8f..18ccd56 100644
--- a/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
+++ b/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
@@ -21,7 +21,7 @@ import java.nio.ByteBuffer;
 import java.util.Date;
 import java.util.List;
 
-import org.apache.cassandra.db.marshal.DateType;
+import org.apache.cassandra.db.marshal.TimestampType;
 import org.apache.cassandra.db.marshal.TimeUUIDType;
 import org.apache.cassandra.db.marshal.LongType;
 import org.apache.cassandra.utils.ByteBufferUtil;
@@ -43,27 +43,27 @@ public abstract class TimeuuidFcts
         }
     };
 
-    public static final Function minTimeuuidFct = new 
AbstractFunction("mintimeuuid", TimeUUIDType.instance, DateType.instance)
+    public static final Function minTimeuuidFct = new 
AbstractFunction("mintimeuuid", TimeUUIDType.instance, TimestampType.instance)
     {
         public ByteBuffer execute(List<ByteBuffer> parameters)
         {
-            return 
ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.minTimeUUID(DateType.instance.compose(parameters.get(0)).getTime())));
+            return 
ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.minTimeUUID(TimestampType.instance.compose(parameters.get(0)).getTime())));
         }
     };
 
-    public static final Function maxTimeuuidFct = new 
AbstractFunction("maxtimeuuid", TimeUUIDType.instance, DateType.instance)
+    public static final Function maxTimeuuidFct = new 
AbstractFunction("maxtimeuuid", TimeUUIDType.instance, TimestampType.instance)
     {
         public ByteBuffer execute(List<ByteBuffer> parameters)
         {
-            return 
ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.maxTimeUUID(DateType.instance.compose(parameters.get(0)).getTime())));
+            return 
ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.maxTimeUUID(TimestampType.instance.compose(parameters.get(0)).getTime())));
         }
     };
 
-    public static final Function dateOfFct = new AbstractFunction("dateof", 
DateType.instance, TimeUUIDType.instance)
+    public static final Function dateOfFct = new AbstractFunction("dateof", 
TimestampType.instance, TimeUUIDType.instance)
     {
         public ByteBuffer execute(List<ByteBuffer> parameters)
         {
-            return DateType.instance.decompose(new 
Date(UUIDGen.unixTimestamp(UUIDGen.getUUID(parameters.get(0)))));
+            return TimestampType.instance.decompose(new 
Date(UUIDGen.unixTimestamp(UUIDGen.getUUID(parameters.get(0)))));
         }
     };
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/db/marshal/AbstractType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java 
b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
index 07bf694..c9e94b7 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
@@ -306,4 +306,3 @@ public abstract class AbstractType<T> implements 
Comparator<ByteBuffer>
         return false;
     }
 }
-

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/db/marshal/DateType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DateType.java 
b/src/java/org/apache/cassandra/db/marshal/DateType.java
index dcd8c9f..7de69e8 100644
--- a/src/java/org/apache/cassandra/db/marshal/DateType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DateType.java
@@ -17,37 +17,40 @@
  */
 package org.apache.cassandra.db.marshal;
 
-import static org.apache.cassandra.type.DateSerializer.iso8601Patterns;
-
 import java.nio.ByteBuffer;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.type.AbstractSerializer;
-import org.apache.cassandra.type.DateSerializer;
+import org.apache.cassandra.type.TimestampSerializer;
 import org.apache.cassandra.type.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.commons.lang.time.DateUtils;
 
 public class DateType extends AbstractType<Date>
 {
+    private static final Logger logger = 
LoggerFactory.getLogger(DateType.class);
+
     public static final DateType instance = new DateType();
 
-    static final String DEFAULT_FORMAT = iso8601Patterns[3];
+    static final String DEFAULT_FORMAT = 
TimestampSerializer.iso8601Patterns[3];
     static final SimpleDateFormat FORMATTER = new 
SimpleDateFormat(DEFAULT_FORMAT);
 
     DateType() {} // singleton
 
     public Date compose(ByteBuffer bytes)
     {
-        return DateSerializer.instance.serialize(bytes);
+        return TimestampSerializer.instance.serialize(bytes);
     }
 
     public ByteBuffer decompose(Date value)
     {
-        return DateSerializer.instance.deserialize(value);
+        return TimestampSerializer.instance.deserialize(value);
     }
 
     public int compare(ByteBuffer o1, ByteBuffer o2)
@@ -66,7 +69,7 @@ public class DateType extends AbstractType<Date>
 
     public String getString(ByteBuffer bytes)
     {
-        return DateSerializer.instance.getString(bytes);
+        return TimestampSerializer.instance.getString(bytes);
     }
 
     public ByteBuffer fromString(String source) throws MarshalException
@@ -103,7 +106,7 @@ public class DateType extends AbstractType<Date>
       {
           try
           {
-              millis = DateUtils.parseDateStrictly(source, 
iso8601Patterns).getTime();
+              millis = DateUtils.parseDateStrictly(source, 
TimestampSerializer.iso8601Patterns).getTime();
           }
           catch (ParseException e1)
           {
@@ -114,18 +117,31 @@ public class DateType extends AbstractType<Date>
       return millis;
     }
 
-    public void validate(ByteBuffer bytes) throws MarshalException
+    @Override
+    public boolean isCompatibleWith(AbstractType<?> previous)
     {
-        DateSerializer.instance.validate(bytes);
+        if (super.isCompatibleWith(previous))
+            return true;
+
+        if (previous instanceof TimestampType)
+        {
+            logger.warn("Changing from TimestampType to DateType is allowed, 
but be wary that they sort differently for pre-unix-epoch timestamps "
+                      + "(negative timestamp values) and thus this change will 
corrupt your data if you have such negative timestamp. There is no "
+                      + "reason to switch from DateType to TimestampType 
except if you were using DateType in the first place and switched to "
+                      + "TimestampType by mistake.");
+            return true;
+        }
+
+        return false;
     }
 
-    public CQL3Type asCQL3Type()
+    public void validate(ByteBuffer bytes) throws MarshalException
     {
-        return CQL3Type.Native.TIMESTAMP;
+        TimestampSerializer.instance.validate(bytes);
     }
 
     public AbstractSerializer<Date> asComposer()
     {
-        return DateSerializer.instance;
+        return TimestampSerializer.instance;
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/db/marshal/LongType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/LongType.java 
b/src/java/org/apache/cassandra/db/marshal/LongType.java
index 45edc2f..2570418 100644
--- a/src/java/org/apache/cassandra/db/marshal/LongType.java
+++ b/src/java/org/apache/cassandra/db/marshal/LongType.java
@@ -43,6 +43,11 @@ public class LongType extends AbstractType<Long>
 
     public int compare(ByteBuffer o1, ByteBuffer o2)
     {
+        return compareLongs(o1, o2);
+    }
+
+    public static int compareLongs(ByteBuffer o1, ByteBuffer o2)
+    {
         if (o1.remaining() == 0)
         {
             return o2.remaining() == 0 ? 0 : -1;
@@ -52,11 +57,10 @@ public class LongType extends AbstractType<Long>
             return 1;
         }
 
-        int diff = o1.get(o1.position()) - o2.get(o2.position());
+        int diff = o1.get(o1.position() + o1.arrayOffset()) - 
o2.get(o2.position() + o2.arrayOffset());
         if (diff != 0)
             return diff;
 
-
         return ByteBufferUtil.compareUnsigned(o1, o2);
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/db/marshal/TimestampType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimestampType.java 
b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
new file mode 100644
index 0000000..ee2140c
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.db.marshal;
+
+import java.nio.ByteBuffer;
+import java.text.ParseException;
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.type.AbstractSerializer;
+import org.apache.cassandra.type.MarshalException;
+import org.apache.cassandra.type.TimestampSerializer;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.commons.lang.time.DateUtils;
+
+/**
+ * Type for date-time values.
+ *
+ * This is meant as a replacement for DateType, as DateType wrongly compare
+ * pre-unix-epoch dates, sorting them *after* post-unix-epoch ones (due to it's
+ * use of unsigned bytes comparison).
+ */
+public class TimestampType extends AbstractType<Date>
+{
+    private static final Logger logger = 
LoggerFactory.getLogger(TimestampType.class);
+
+    public static final TimestampType instance = new TimestampType();
+
+    private TimestampType() {} // singleton
+
+    public Date compose(ByteBuffer bytes)
+    {
+        return TimestampSerializer.instance.serialize(bytes);
+    }
+
+    public ByteBuffer decompose(Date value)
+    {
+        return TimestampSerializer.instance.deserialize(value);
+    }
+
+    public int compare(ByteBuffer o1, ByteBuffer o2)
+    {
+        return LongType.compareLongs(o1, o2);
+    }
+
+    public String getString(ByteBuffer bytes)
+    {
+        return TimestampSerializer.instance.getString(bytes);
+    }
+
+    public ByteBuffer fromString(String source) throws MarshalException
+    {
+      // Return an empty ByteBuffer for an empty string.
+      if (source.isEmpty())
+          return ByteBufferUtil.EMPTY_BYTE_BUFFER;
+
+      return ByteBufferUtil.bytes(dateStringToTimestamp(source));
+    }
+
+    public static long dateStringToTimestamp(String source) throws 
MarshalException
+    {
+      long millis;
+
+      if (source.toLowerCase().equals("now"))
+      {
+          millis = System.currentTimeMillis();
+      }
+      // Milliseconds since epoch?
+      else if (source.matches("^\\d+$"))
+      {
+          try
+          {
+              millis = Long.parseLong(source);
+          }
+          catch (NumberFormatException e)
+          {
+              throw new MarshalException(String.format("unable to make long 
(for date) from: '%s'", source), e);
+          }
+      }
+      // Last chance, attempt to parse as date-time string
+      else
+      {
+          try
+          {
+              millis = DateUtils.parseDateStrictly(source, 
TimestampSerializer.iso8601Patterns).getTime();
+          }
+          catch (ParseException e1)
+          {
+              throw new MarshalException(String.format("unable to coerce '%s' 
to a  formatted date (long)", source), e1);
+          }
+      }
+
+      return millis;
+    }
+
+    public void validate(ByteBuffer bytes) throws MarshalException
+    {
+        TimestampSerializer.instance.validate(bytes);
+    }
+
+    @Override
+    public boolean isCompatibleWith(AbstractType<?> previous)
+    {
+        if (super.isCompatibleWith(previous))
+            return true;
+
+        if (previous instanceof DateType)
+        {
+            logger.warn("Changing from DateType to TimestampType is allowed, 
but be wary that they sort differently for pre-unix-epoch timestamps "
+                      + "(negative timestamp values) and thus this change will 
corrupt your data if you have such negative timestamp. So unless you "
+                      + "know that you don't have *any* pre-unix-epoch 
timestamp you should change back to DateType");
+            return true;
+        }
+
+        return false;
+    }
+
+    public CQL3Type asCQL3Type()
+    {
+        return CQL3Type.Native.TIMESTAMP;
+    }
+
+    public AbstractSerializer<Date> asComposer()
+    {
+        return TimestampSerializer.instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/db/marshal/UUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java 
b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
index 159cab3..73021ee 100644
--- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
@@ -30,7 +30,7 @@ import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 import org.apache.commons.lang.time.DateUtils;
 
-import static org.apache.cassandra.type.DateSerializer.iso8601Patterns;
+import static org.apache.cassandra.type.TimestampSerializer.iso8601Patterns;
 
 /**
  * Compares UUIDs using the following criteria:<br>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java 
b/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
index d1bc5e4..9636cea 100644
--- a/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
+++ b/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
@@ -140,7 +140,7 @@ public abstract class AbstractCassandraStorage extends 
LoadFunc implements Store
        else if (value instanceof UUID)
            pair.set(position, new 
DataByteArray(UUIDGen.decompose((java.util.UUID) value)));
        else if (value instanceof Date)
-           pair.set(position, DateType.instance.decompose((Date) 
value).getLong());
+           pair.set(position, TimestampType.instance.decompose((Date) 
value).getLong());
        else
            pair.set(position, value);
     }
@@ -299,7 +299,7 @@ public abstract class AbstractCassandraStorage extends 
LoadFunc implements Store
     /** get pig type for the cassandra data type*/
     protected byte getPigType(AbstractType type)
     {
-        if (type instanceof LongType || type instanceof DateType) // DateType 
is bad and it should feel bad
+        if (type instanceof LongType || type instanceof DateType || type 
instanceof TimestampType) // DateType is bad and it should feel bad
             return DataType.LONG;
         else if (type instanceof IntegerType || type instanceof Int32Type) // 
IntegerType will overflow at 2**31, but is kept for compatibility until pig has 
a BigInteger
             return DataType.INTEGER;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/tools/Shuffle.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/Shuffle.java 
b/src/java/org/apache/cassandra/tools/Shuffle.java
index 5749a81..0c5c92a 100644
--- a/src/java/org/apache/cassandra/tools/Shuffle.java
+++ b/src/java/org/apache/cassandra/tools/Shuffle.java
@@ -43,7 +43,7 @@ import javax.management.MBeanServerConnection;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
-import org.apache.cassandra.type.DateSerializer;
+import org.apache.cassandra.type.TimestampSerializer;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.dht.Token;
 import org.apache.cassandra.locator.EndpointSnitchInfoMBean;
@@ -389,7 +389,7 @@ public class Shuffle extends AbstractJmxClient
 
                 ByteBuffer tokenBytes = 
ByteBuffer.wrap(row.getColumns().get(0).getValue());
                 ByteBuffer requestedAt = 
ByteBuffer.wrap(row.getColumns().get(1).getValue());
-                Date time = DateSerializer.instance.serialize(requestedAt);
+                Date time = 
TimestampSerializer.instance.serialize(requestedAt);
                 Token<?> token = 
partitioner.getTokenFactory().fromByteArray(tokenBytes);
 
                 writeln("%-42s %-15s %s", token.toString(), host, 
time.toString());

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/transport/DataType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/DataType.java 
b/src/java/org/apache/cassandra/transport/DataType.java
index 21f4d03..b590042 100644
--- a/src/java/org/apache/cassandra/transport/DataType.java
+++ b/src/java/org/apache/cassandra/transport/DataType.java
@@ -43,7 +43,7 @@ public enum DataType implements 
OptionCodec.Codecable<DataType>
     FLOAT    (8,  FloatType.instance),
     INT      (9,  Int32Type.instance),
     TEXT     (10, UTF8Type.instance),
-    TIMESTAMP(11, DateType.instance),
+    TIMESTAMP(11, TimestampType.instance),
     UUID     (12, UUIDType.instance),
     VARCHAR  (13, UTF8Type.instance),
     VARINT   (14, IntegerType.instance),
@@ -146,6 +146,9 @@ public enum DataType implements 
OptionCodec.Codecable<DataType>
         // shouldn't have to care about it.
         if (type instanceof ReversedType)
             type = ((ReversedType)type).baseType;
+        // For compatibility sake, we still return DateType as the timestamp 
type in resultSet metadata (#5723)
+        else if (type instanceof DateType)
+            type = TimestampType.instance;
 
         DataType dt = dataTypeMap.get(type);
         if (dt == null)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/type/DateSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/type/DateSerializer.java 
b/src/java/org/apache/cassandra/type/DateSerializer.java
deleted file mode 100644
index 4f0186c..0000000
--- a/src/java/org/apache/cassandra/type/DateSerializer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.cassandra.type;
-
-import org.apache.cassandra.utils.ByteBufferUtil;
-
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-public class DateSerializer extends AbstractSerializer<Date>
-{
-    public static final String[] iso8601Patterns = new String[] {
-            "yyyy-MM-dd HH:mm",
-            "yyyy-MM-dd HH:mm:ss",
-            "yyyy-MM-dd HH:mmZ",
-            "yyyy-MM-dd HH:mm:ssZ",
-            "yyyy-MM-dd'T'HH:mm",
-            "yyyy-MM-dd'T'HH:mmZ",
-            "yyyy-MM-dd'T'HH:mm:ss",
-            "yyyy-MM-dd'T'HH:mm:ssZ",
-            "yyyy-MM-dd",
-            "yyyy-MM-ddZ"
-    };
-
-    static final String DEFAULT_FORMAT = iso8601Patterns[3];
-
-    static final ThreadLocal<SimpleDateFormat> FORMATTER = new 
ThreadLocal<SimpleDateFormat>()
-    {
-        protected SimpleDateFormat initialValue()
-        {
-            return new SimpleDateFormat(DEFAULT_FORMAT);
-        }
-    };
-
-    public static final DateSerializer instance = new DateSerializer();
-
-    @Override
-    public Date serialize(ByteBuffer bytes)
-    {
-        return bytes.remaining() > 0
-                ? new Date(ByteBufferUtil.toLong(bytes))
-                : null;
-    }
-
-    @Override
-    public ByteBuffer deserialize(Date value)
-    {
-        return (value == null)
-                ? ByteBufferUtil.EMPTY_BYTE_BUFFER
-                : ByteBufferUtil.bytes(value.getTime());
-    }
-
-    @Override
-    public void validate(ByteBuffer bytes) throws MarshalException
-    {
-        if (bytes.remaining() != 8 && bytes.remaining() != 0)
-            throw new MarshalException(String.format("Expected 8 or 0 byte 
long for date (%d)", bytes.remaining()));
-    }
-
-    @Override
-    public String getString(ByteBuffer bytes)
-    {
-        if (bytes.remaining() == 0)
-        {
-            return "";
-        }
-        if (bytes.remaining() != 8)
-        {
-            throw new MarshalException("A date is exactly 8 bytes (stored as a 
long): " + bytes.remaining());
-        }
-
-        // uses ISO-8601 formatted string
-        return FORMATTER.get().format(new Date(ByteBufferUtil.toLong(bytes)));
-    }
-
-    @Override
-    public String toString(Date value)
-    {
-        return FORMATTER.get().format(value);
-    }
-
-    @Override
-    public Class<Date> getType()
-    {
-        return Date.class;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9ec7b808/src/java/org/apache/cassandra/type/TimestampSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/type/TimestampSerializer.java 
b/src/java/org/apache/cassandra/type/TimestampSerializer.java
new file mode 100644
index 0000000..84042e1
--- /dev/null
+++ b/src/java/org/apache/cassandra/type/TimestampSerializer.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.type;
+
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+import java.nio.ByteBuffer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class TimestampSerializer extends AbstractSerializer<Date>
+{
+    public static final String[] iso8601Patterns = new String[] {
+            "yyyy-MM-dd HH:mm",
+            "yyyy-MM-dd HH:mm:ss",
+            "yyyy-MM-dd HH:mmZ",
+            "yyyy-MM-dd HH:mm:ssZ",
+            "yyyy-MM-dd'T'HH:mm",
+            "yyyy-MM-dd'T'HH:mmZ",
+            "yyyy-MM-dd'T'HH:mm:ss",
+            "yyyy-MM-dd'T'HH:mm:ssZ",
+            "yyyy-MM-dd",
+            "yyyy-MM-ddZ"
+    };
+
+    static final String DEFAULT_FORMAT = iso8601Patterns[3];
+
+    static final ThreadLocal<SimpleDateFormat> FORMATTER = new 
ThreadLocal<SimpleDateFormat>()
+    {
+        protected SimpleDateFormat initialValue()
+        {
+            return new SimpleDateFormat(DEFAULT_FORMAT);
+        }
+    };
+
+    public static final TimestampSerializer instance = new 
TimestampSerializer();
+
+    @Override
+    public Date serialize(ByteBuffer bytes)
+    {
+        return bytes.remaining() > 0
+                ? new Date(ByteBufferUtil.toLong(bytes))
+                : null;
+    }
+
+    @Override
+    public ByteBuffer deserialize(Date value)
+    {
+        return (value == null)
+                ? ByteBufferUtil.EMPTY_BYTE_BUFFER
+                : ByteBufferUtil.bytes(value.getTime());
+    }
+
+    @Override
+    public void validate(ByteBuffer bytes) throws MarshalException
+    {
+        if (bytes.remaining() != 8 && bytes.remaining() != 0)
+            throw new MarshalException(String.format("Expected 8 or 0 byte 
long for date (%d)", bytes.remaining()));
+    }
+
+    @Override
+    public String getString(ByteBuffer bytes)
+    {
+        if (bytes.remaining() == 0)
+        {
+            return "";
+        }
+        if (bytes.remaining() != 8)
+        {
+            throw new MarshalException("A date is exactly 8 bytes (stored as a 
long): " + bytes.remaining());
+        }
+
+        // uses ISO-8601 formatted string
+        return FORMATTER.get().format(new Date(ByteBufferUtil.toLong(bytes)));
+    }
+
+    @Override
+    public String toString(Date value)
+    {
+        return FORMATTER.get().format(value);
+    }
+
+    @Override
+    public Class<Date> getType()
+    {
+        return Date.class;
+    }
+}

Reply via email to