diff --git a/CHANGES.txt b/CHANGES.txt index c12cc50631..c17f85f3ed 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -66,6 +66,7 @@ Merged from 2.1: * Gossiper#isEnabled is not thread safe (CASSANDRA-11116) * Avoid major compaction mixing repaired and unrepaired sstables in DTCS (CASSANDRA-11113) * Make it clear what DTCS timestamp_resolution is used for (CASSANDRA-11041) + * (cqlsh) Display milliseconds when datetime overflows (CASSANDRA-10625) 3.3 diff --git a/bin/cqlsh.py b/bin/cqlsh.py index 06cf80561f..3d7ea5dec2 100644 --- a/bin/cqlsh.py +++ b/bin/cqlsh.py @@ -152,10 +152,13 @@ except ImportError, e: from cassandra.auth import PlainTextAuthProvider from cassandra.cluster import Cluster +from cassandra.marshal import int64_unpack from cassandra.metadata import (ColumnMetadata, KeyspaceMetadata, TableMetadata, protect_name, protect_names) from cassandra.policies import WhiteListRoundRobinPolicy from cassandra.query import SimpleStatement, ordered_dict_factory, TraceUnavailable +from cassandra.type_codes import DateType +from cassandra.util import datetime_from_timestamp # cqlsh should run correctly when run out of a Cassandra source tree, # out of an unpacked Cassandra tarball, and after a proper package install. @@ -604,10 +607,24 @@ def insert_driver_hooks(): def extend_cql_deserialization(): - """ - The python driver returns BLOBs as string, but we expect them as bytearrays - """ + # The python driver returns BLOBs as string, but we expect them as bytearrays cassandra.cqltypes.BytesType.deserialize = staticmethod(lambda byts, protocol_version: bytearray(byts)) + + class DateOverFlowWarning(RuntimeWarning): + pass + + # Native datetime types blow up outside of datetime.[MIN|MAX]_YEAR. We will fall back to an int timestamp + def deserialize_date_fallback_int(byts, protocol_version): + timestamp_ms = int64_unpack(byts) + try: + return datetime_from_timestamp(timestamp_ms / 1000.0) + except OverflowError: + warnings.warn(DateOverFlowWarning("Some timestamps are larger than Python datetime can represent. Timestamps are displayed in milliseconds from epoch.")) + return timestamp_ms + + cassandra.cqltypes.DateType.deserialize = staticmethod(deserialize_date_fallback_int) + + # Return cassandra.cqltypes.EMPTY instead of None for empty values cassandra.cqltypes.CassandraType.support_empty_values = True