Revert "Add date and time types" on 2.1 branch

This reverts commit 107545b392.

Conflicts:
	CHANGES.txt
	NEWS.txt
	bin/cqlsh
	pylib/cqlshlib/test/test_keyspace_init.cql
This commit is contained in:
Joshua McKenzie 2015-04-21 08:42:31 -05:00
parent f18fb04452
commit 7f29201ce2
26 changed files with 78 additions and 1472 deletions

View File

@ -43,7 +43,6 @@
* Fix cassandra-stress so it respects the CL passed in user mode (CASSANDRA-8948)
* Fix rare NPE in ColumnDefinition#hasIndexOption() (CASSANDRA-8786)
* cassandra-stress reports per-operation statistics, plus misc (CASSANDRA-8769)
* Add SimpleDate (cql date) and Time (cql time) types (CASSANDRA-7523)
* Use long for key count in cfstats (CASSANDRA-8913)
* Make SSTableRewriter.abort() more robust to failure (CASSANDRA-8832)
* Remove cold_reads_to_omit from STCS (CASSANDRA-8860)

View File

@ -21,16 +21,11 @@ Upgrading
removed - it is almost always better to use date tiered compaction for
workloads that have cold data.
New features
------------
- New `SimpleDateType` (cql date). 4-byte unsigned integer w/out timestamp
- New `TimeType` (cql time). 8-byte long nano-second resolution timestamp
2.1.4
=====
The default JMX config now listens to localhost only. You must enable
the other JMX flags in cassandra-env.sh manually.
2.1.3
=====

View File

@ -126,10 +126,6 @@ from cqlshlib.displaying import (RED, BLUE, CYAN, ANSI_RESET, COLUMN_NAME_COLORS
FormattedValue, colorme)
from cqlshlib.formatting import format_by_type, formatter_for, format_value_utype
from cqlshlib.util import trim_if_present, get_file_encoding_bomsize
from cqlshlib.formatting import DateTimeFormat
from cqlshlib.formatting import DEFAULT_TIMESTAMP_FORMAT
from cqlshlib.formatting import DEFAULT_DATE_FORMAT
from cqlshlib.formatting import DEFAULT_NANOTIME_FORMAT
from cqlshlib.tracing import print_trace_session, print_trace
DEFAULT_HOST = '127.0.0.1'
@ -137,6 +133,7 @@ DEFAULT_PORT = 9042
DEFAULT_CQLVER = '3.2.0'
DEFAULT_PROTOCOL_VERSION = 3
DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S%z'
DEFAULT_FLOAT_PRECISION = 5
DEFAULT_MAX_TRACE_WAIT = 10
@ -438,7 +435,7 @@ def full_cql_version(ver):
vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
return ver, vertuple
def format_value(val, output_encoding, addcolor=False, date_time_format=None,
def format_value(val, output_encoding, addcolor=False, time_format=None,
float_precision=None, colormap=None, nullval=None):
if isinstance(val, DecodeError):
if addcolor:
@ -446,7 +443,7 @@ def format_value(val, output_encoding, addcolor=False, date_time_format=None,
else:
return FormattedValue(repr(val.thebytes))
return format_by_type(type(val), val, output_encoding, colormap=colormap,
addcolor=addcolor, nullval=nullval, date_time_format=date_time_format,
addcolor=addcolor, nullval=nullval, time_format=time_format,
float_precision=float_precision)
def show_warning_without_quoting_line(message, category, filename, lineno, file=None, line=None):
@ -536,9 +533,7 @@ class Shell(cmd.Cmd):
completekey=DEFAULT_COMPLETEKEY, use_conn=None,
cqlver=DEFAULT_CQLVER, keyspace=None,
tracing_enabled=False, expand_enabled=False,
display_nanotime_format=DEFAULT_NANOTIME_FORMAT,
display_timestamp_format=DEFAULT_TIMESTAMP_FORMAT,
display_date_format=DEFAULT_DATE_FORMAT,
display_time_format=DEFAULT_TIME_FORMAT,
display_float_precision=DEFAULT_FLOAT_PRECISION,
max_trace_wait=DEFAULT_MAX_TRACE_WAIT,
ssl=False,
@ -574,11 +569,7 @@ class Shell(cmd.Cmd):
self.session = self.conn.connect()
self.color = color
self.display_nanotime_format = display_nanotime_format
self.display_timestamp_format = display_timestamp_format
self.display_date_format = display_date_format
self.display_time_format = display_time_format
self.display_float_precision = display_float_precision
# Workaround for CASSANDRA-8521 until PYTHON-205 is resolved.
@ -602,10 +593,6 @@ class Shell(cmd.Cmd):
self.current_keyspace = keyspace
self.display_timestamp_format = display_timestamp_format
self.display_nanotime_format = display_nanotime_format
self.display_date_format = display_date_format
self.max_trace_wait = max_trace_wait
self.session.max_trace_wait = max_trace_wait
if encoding is None:
@ -652,10 +639,8 @@ class Shell(cmd.Cmd):
if isinstance(val, DecodeError):
self.decoding_errors.append(val)
try:
dtformats = DateTimeFormat(timestamp_format=self.display_timestamp_format,
date_format=self.display_date_format, nanotime_format=self.display_nanotime_format)
return format_value(val, self.output_codec.name,
addcolor=self.color, date_time_format=dtformats,
addcolor=self.color, time_format=self.display_time_format,
float_precision=self.display_float_precision, **kwargs)
except Exception, e:
err = FormatError(val, e)
@ -1717,7 +1702,7 @@ class Shell(cmd.Cmd):
return 0
wmeter = meter.Meter()
try:
dtformats = DateTimeFormat(self.display_timestamp_format, self.display_date_format, self.display_nanotime_format)
dump = self.prep_export_dump(ks, cf, columns)
writer = csv.writer(csvdest, **dialect_options)
if header:
@ -1725,7 +1710,7 @@ class Shell(cmd.Cmd):
for row in dump:
fmt = lambda v: \
format_value(v, output_encoding=encoding, nullval=nullval,
date_time_format=dtformats,
time_format=self.display_time_format,
float_precision=self.display_float_precision).strval
writer.writerow(map(fmt, row.values()))
wmeter.mark_written()
@ -1807,9 +1792,7 @@ class Shell(cmd.Cmd):
subshell = Shell(self.hostname, self.port,
color=self.color, encoding=self.encoding, stdin=f,
tty=False, use_conn=self.conn, cqlver=self.cql_version,
display_timestamp_format=self.display_timestamp_format,
display_date_format=self.display_date_format,
display_nanotime_format=self.display_nanotime_format,
display_time_format=self.display_time_format,
display_float_precision=self.display_float_precision,
max_trace_wait=self.max_trace_wait)
subshell.cmdloop()
@ -2117,11 +2100,7 @@ def read_options(cmdlineargs, environment):
DEFAULT_COMPLETEKEY)
optvalues.color = option_with_default(configs.getboolean, 'ui', 'color')
optvalues.time_format = raw_option_with_default(configs, 'ui', 'time_format',
DEFAULT_TIMESTAMP_FORMAT)
optvalues.nanotime_format = raw_option_with_default(configs, 'ui', 'nanotime_format',
DEFAULT_NANOTIME_FORMAT)
optvalues.date_format = raw_option_with_default(configs, 'ui', 'date_format',
DEFAULT_DATE_FORMAT)
DEFAULT_TIME_FORMAT)
optvalues.float_precision = option_with_default(configs.getint, 'ui', 'float_precision',
DEFAULT_FLOAT_PRECISION)
optvalues.field_size_limit = option_with_default(configs.getint, 'csv', 'field_size_limit', csv.field_size_limit())
@ -2241,9 +2220,7 @@ def main(options, hostname, port):
completekey=options.completekey,
cqlver=options.cqlversion,
keyspace=options.keyspace,
display_timestamp_format=options.time_format,
display_nanotime_format=options.nanotime_format,
display_date_format=options.date_format,
display_time_format=options.time_format,
display_float_precision=options.float_precision,
max_trace_wait=options.max_trace_wait,
ssl=options.ssl,

View File

@ -944,14 +944,12 @@ bc(syntax)..
| blob
| boolean
| counter
| date
| decimal
| double
| float
| inet
| int
| text
| time
| timestamp
| timeuuid
| uuid
@ -972,15 +970,13 @@ p. The following table gives additional informations on the native data types, a
|@blob@ | blobs |Arbitrary bytes (no validation)|
|@boolean@ | booleans |true or false|
|@counter@ | integers |Counter column (64-bit signed value). See "Counters":#counters for details|
|@date@ | integers, strings |A date (with no corresponding time value). See "Working with dates":#usingdates below for more information.|
|@decimal@ | integers, floats |Variable-precision decimal|
|@double@ | integers |64-bit IEEE-754 floating point|
|@float@ | integers, floats |32-bit IEEE-754 floating point|
|@inet@ | strings |An IP address. It can be either 4 bytes long (IPv4) or 16 bytes long (IPv6). There is no @inet@ constant, IP address should be inputed as strings|
|@int@ | integers |32-bit signed int|
|@text@ | strings |UTF8 encoded string|
|@time@ | integers, strings |A time with nanosecond precision. See "Working with time":#usingtime below for more information.|
|@timestamp@| integers, strings |A timestamp. Strings constant are allow to input timestamps as dates, see "Working with timestamps":#usingtimestamps below for more information.|
|@timestamp@| integers, strings |A timestamp. Strings constant are allow to input timestamps as dates, see "Working with dates":#usingdates below for more information.|
|@timeuuid@ | uuids |Type 1 UUID. This is generally used as a "conflict-free" timestamp. Also see the "functions on Timeuuid":#timeuuidFun|
|@uuid@ | uuids |Type 1 or type 4 UUID|
|@varchar@ | strings |UTF8 encoded string|
@ -988,7 +984,7 @@ p. The following table gives additional informations on the native data types, a
For more information on how to use the collection types, see the "Working with collections":#collections section below.
h3(#usingtimestamps). Working with timestamps
h3(#usingdates). Working with dates
Values of the @timestamp@ type are encoded as 64-bit signed integers representing a number of milliseconds since the standard base time known as "the epoch": January 1 1970 at 00:00:00 GMT.
@ -1022,31 +1018,6 @@ The time of day may also be omitted, if the date is the only piece that matters:
In that case, the time of day will default to 00:00:00, in the specified or default time zone.
h3(#usingdates). Working with dates
Values of the @date@ type are encoded as 32-bit unsigned integers representing a number of days with "the epoch" at the center of the range (2^31). Epoch is January 1st, 1970
A date can be input in CQL as an unsigned integer as defined above.
They can also be input as string literals in the following format:
* @2014-01-01@
h3(#usingtime). Working with time
Values of the @time@ type are encoded as 64-bit signed integers representing the number of nanoseconds since midnight.
A time can be input in CQL as simple long integers, giving the number of nanoseconds since midnight.
They can also be input as string literals in any of the following formats:
* @08:12:54@
* @08:12:54.123@
* @08:12:54.123456@
* @08:12:54.123456789@
h3(#counters). Counters
The @counter@ type is used to define _counter columns_. A counter column is a column whose value is a 64-bit signed integer and on which 2 operations are supported: incrementation and decrementation (see "@UPDATE@":#updateStmt for syntax). Note the value of a counter cannot be set. A counter doesn't exist until first incremented/decremented, and the first incrementation/decrementation is made as if the previous value was 0. Deletion of counter columns is supported but have some limitations (see the "Cassandra Wiki":http://wiki.apache.org/cassandra/Counters for more information).
@ -1211,7 +1182,7 @@ will never return any result by design, since the value returned by @now()@ is g
h4. @minTimeuuid@ and @maxTimeuuid@
The @minTimeuuid@ (resp. @maxTimeuuid@) function takes a @timestamp@ value @t@ (which can be "either a timestamp or a date string":#usingtimestamps) and return a _fake_ @timeuuid@ corresponding to the _smallest_ (resp. _biggest_) possible @timeuuid@ having for timestamp @t@. So for instance:
The @minTimeuuid@ (resp. @maxTimeuuid@) function takes a @timestamp@ value @t@ (which can be "either a timestamp or a date string":#usingdates) and return a _fake_ @timeuuid@ corresponding to the _smallest_ (resp. _biggest_) possible @timeuuid@ having for timestamp @t@. So for instance:
bc(sample).
SELECT * FROM myTable WHERE t > maxTimeuuid('2013-01-01 00:05+0000') AND t < minTimeuuid('2013-02-02 10:00+0000')
@ -1319,8 +1290,6 @@ CQL distinguishes between _reserved_ and _non-reserved_ keywords. Reserved keywo
| @WITH@ | yes |
| @WRITETIME@ | no |
| @DISTINCT@ | no |
| @DATE@ | no |
| @TIME@ | no |
h2(#appendixB). Appendix B: CQL Reserved Types
@ -1369,7 +1338,7 @@ h3. 3.1.4
h3. 3.1.3
* Millisecond precision formats have been added to the timestamp parser (see "working with dates":#usingtimestamps).
* Millisecond precision formats have been added to the timestamp parser (see "working with dates":#usingdates).
h3. 3.1.2
@ -1409,7 +1378,7 @@ h3. 3.0.2
h3. 3.0.1
* "Date strings":#usingtimestamps (and timestamps) are no longer accepted as valid @timeuuid@ values. Doing so was a bug in the sense that date string are not valid @timeuuid@, and it was thus resulting in "confusing behaviors":https://issues.apache.org/jira/browse/CASSANDRA-4936. However, the following new methods have been added to help working with @timeuuid@: @now@, @minTimeuuid@, @maxTimeuuid@ , @dateOf@ and @unixTimestampOf@. See the "section dedicated to these methods":#usingtimeuuid for more detail.
* "Date strings":#usingdates (and timestamps) are no longer accepted as valid @timeuuid@ values. Doing so was a bug in the sense that date string are not valid @timeuuid@, and it was thus resulting in "confusing behaviors":https://issues.apache.org/jira/browse/CASSANDRA-4936. However, the following new methods have been added to help working with @timeuuid@: @now@, @minTimeuuid@, @maxTimeuuid@ , @dateOf@ and @unixTimestampOf@. See the "section dedicated to these methods":#usingtimeuuid for more detail.
* "Float constants"#constants now support the exponent notation. In other words, @4.2E10@ is now a valid floating point value.

Binary file not shown.

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed 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.

View File

@ -19,8 +19,8 @@ from cassandra.metadata import maybe_escape_name
from cassandra.metadata import escape_name
simple_cql_types = set(('ascii', 'bigint', 'blob', 'boolean', 'counter', 'date', 'decimal', 'double', 'float', 'inet', 'int',
'text', 'time', 'timestamp', 'timeuuid', 'uuid', 'varchar', 'varint'))
simple_cql_types = set(('ascii', 'bigint', 'blob', 'boolean', 'counter', 'decimal', 'double', 'float', 'inet', 'int',
'text', 'timestamp', 'timeuuid', 'uuid', 'varchar', 'varint'))
simple_cql_types.difference_update(('set', 'map', 'list'))
from . import helptopics
@ -42,7 +42,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
'limit', 'using', 'use', 'count', 'set',
'begin', 'apply', 'batch', 'truncate', 'delete', 'in', 'create',
'keyspace', 'schema', 'columnfamily', 'table', 'index', 'on', 'drop',
'primary', 'into', 'values', 'date', 'time', 'timestamp', 'ttl', 'alter', 'add', 'type',
'primary', 'into', 'values', 'timestamp', 'ttl', 'alter', 'add', 'type',
'compact', 'storage', 'order', 'by', 'asc', 'desc', 'clustering',
'token', 'writetime', 'map', 'list', 'to', 'custom', 'if', 'not'
))

View File

@ -95,8 +95,6 @@ DEFAULT_VALUE_COLORS = dict(
error=RED,
blob=DARK_MAGENTA,
timestamp=GREEN,
date=GREEN,
time=GREEN,
int=GREEN,
float=GREEN,
decimal=GREEN,

View File

@ -14,15 +14,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import calendar
import math
import re
import time
import sys
import calendar
import math
from collections import defaultdict
from . import wcwidth
from .displaying import colorme, FormattedValue, DEFAULT_VALUE_COLORS
from datetime import datetime, timedelta
from cassandra.cqltypes import EMPTY
unicode_controlchars_re = re.compile(r'[\x00-\x31\x7f-\xa0]')
@ -47,12 +45,13 @@ def _make_turn_bits_red_f(color1, color2):
return _turn_bits_red
default_null_placeholder = 'null'
default_time_format = ''
default_float_precision = 3
default_colormap = DEFAULT_VALUE_COLORS
empty_colormap = defaultdict(lambda: '')
def format_by_type(cqltype, val, encoding, colormap=None, addcolor=False,
nullval=None, date_time_format=None, float_precision=None):
nullval=None, time_format=None, float_precision=None):
if nullval is None:
nullval = default_null_placeholder
if val is None:
@ -61,12 +60,12 @@ def format_by_type(cqltype, val, encoding, colormap=None, addcolor=False,
colormap = empty_colormap
elif colormap is None:
colormap = default_colormap
if date_time_format is None:
date_time_format = DateTimeFormat()
if time_format is None:
time_format = default_time_format
if float_precision is None:
float_precision = default_float_precision
return format_value(cqltype, val, encoding=encoding, colormap=colormap,
date_time_format=date_time_format, float_precision=float_precision,
time_format=time_format, float_precision=float_precision,
nullval=nullval)
def color_text(bval, colormap, displaywidth=None):
@ -87,16 +86,6 @@ def color_text(bval, colormap, displaywidth=None):
displaywidth -= bval.count(r'\\')
return FormattedValue(bval, coloredval, displaywidth)
DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
DEFAULT_DATE_FORMAT = '%Y-%m-%d'
DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
class DateTimeFormat():
def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT, nanotime_format=DEFAULT_NANOTIME_FORMAT):
self.timestamp_format=timestamp_format
self.date_format=date_format
self.nanotime_format=nanotime_format
def format_value_default(val, colormap, **_):
val = str(val)
escapedval = val.replace('\\', '\\\\')
@ -168,13 +157,15 @@ def format_integer_type(val, colormap, **_):
formatter_for('long')(format_integer_type)
formatter_for('int')(format_integer_type)
@formatter_for('datetime')
def format_value_timestamp(val, colormap, date_time_format, quote=False, **_):
bval = strftime(date_time_format.timestamp_format, calendar.timegm(val.utctimetuple()))
@formatter_for('date')
def format_value_timestamp(val, colormap, time_format, quote=False, **_):
bval = strftime(time_format, calendar.timegm(val.utctimetuple()))
if quote:
bval = "'%s'" % bval
return colorme(bval, colormap, 'timestamp')
formatter_for('datetime')(format_value_timestamp)
def strftime(time_format, seconds):
local = time.localtime(seconds)
formatted = time.strftime(time_format, local)
@ -192,14 +183,6 @@ def strftime(time_format, seconds):
hours, minutes = divmod(abs(offset) / 60, 60)
return formatted[:-5] + sign + '{0:0=2}{1:0=2}'.format(hours, minutes)
@formatter_for('date')
def format_value_uuid(val, colormap, **_):
return format_python_formatted_type(val, colormap, 'date')
@formatter_for('Time')
def format_value_time(val, colormap, **_):
return format_python_formatted_type(val, colormap, 'time')
@formatter_for('str')
def format_value_text(val, encoding, colormap, quote=False, **_):
escapedval = val.replace(u'\\', u'\\\\')
@ -216,9 +199,9 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
formatter_for('unicode')(format_value_text)
def format_simple_collection(val, lbracket, rbracket, encoding,
colormap, date_time_format, float_precision, nullval):
colormap, time_format, float_precision, nullval):
subs = [format_value(type(sval), sval, encoding=encoding, colormap=colormap,
date_time_format=date_time_format, float_precision=float_precision,
time_format=time_format, float_precision=float_precision,
nullval=nullval, quote=True)
for sval in val]
bval = lbracket + ', '.join(sval.strval for sval in subs) + rbracket
@ -229,28 +212,28 @@ def format_simple_collection(val, lbracket, rbracket, encoding,
return FormattedValue(bval, coloredval, displaywidth)
@formatter_for('list')
def format_value_list(val, encoding, colormap, date_time_format, float_precision, nullval, **_):
def format_value_list(val, encoding, colormap, time_format, float_precision, nullval, **_):
return format_simple_collection(val, '[', ']', encoding, colormap,
date_time_format, float_precision, nullval)
time_format, float_precision, nullval)
@formatter_for('tuple')
def format_value_tuple(val, encoding, colormap, date_time_format, float_precision, nullval, **_):
def format_value_tuple(val, encoding, colormap, time_format, float_precision, nullval, **_):
return format_simple_collection(val, '(', ')', encoding, colormap,
date_time_format, float_precision, nullval)
time_format, float_precision, nullval)
@formatter_for('set')
def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval, **_):
def format_value_set(val, encoding, colormap, time_format, float_precision, nullval, **_):
return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
date_time_format, float_precision, nullval)
time_format, float_precision, nullval)
formatter_for('frozenset')(format_value_set)
formatter_for('sortedset')(format_value_set)
@formatter_for('dict')
def format_value_map(val, encoding, colormap, date_time_format, float_precision, nullval, **_):
def format_value_map(val, encoding, colormap, time_format, float_precision, nullval, **_):
def subformat(v):
return format_value(type(v), v, encoding=encoding, colormap=colormap,
date_time_format=date_time_format, float_precision=float_precision,
time_format=time_format, float_precision=float_precision,
nullval=nullval, quote=True)
subs = [(subformat(k), subformat(v)) for (k, v) in sorted(val.items())]
@ -267,12 +250,12 @@ formatter_for('OrderedMap')(format_value_map)
formatter_for('OrderedMapSerializedKey')(format_value_map)
def format_value_utype(val, encoding, colormap, date_time_format, float_precision, nullval, **_):
def format_value_utype(val, encoding, colormap, time_format, float_precision, nullval, **_):
def format_field_value(v):
if v is None:
return colorme(nullval, colormap, 'error')
return format_value(type(v), v, encoding=encoding, colormap=colormap,
date_time_format=date_time_format, float_precision=float_precision,
time_format=time_format, float_precision=float_precision,
nullval=nullval, quote=True)
def format_field_name(name):

View File

@ -33,8 +33,6 @@ class CQLHelpTopics(object):
one of the following topics:
HELP TIMESTAMP_INPUT
HELP DATE_INPUT
HELP TIME_INPUT
HELP BLOB_INPUT
HELP UUID_INPUT
HELP BOOLEAN_INPUT
@ -71,27 +69,6 @@ class CQLHelpTopics(object):
server node will be used.
"""
def help_date_input(self):
print """
Date input
CQL supports the following format for date specification:
yyyy-mm-dd
"""
def help_time_input(self):
print """
Time input
CQL supports the following format for time specification:
HH:MM:SS
HH:MM:SS.mmm
HH:MM:SS.mmmuuu
HH:MM:SS.mmmuuunnn
"""
def help_blob_input(self):
print """
Blob input

View File

@ -113,11 +113,10 @@ class TestCqlshOutput(BaseTestCase):
self.assertTrue(6 <= len(output) <= 8,
msg='output: %r' % '\n'.join(output))
self.assertEqual(output[0], '')
self.assertEqual(output[1], 'Warning! Non-ISO 8601 dates detected (< 1-1-1 or > 9999-12-31). Returning raw days since epoch.');
self.assertNicelyFormattedTableHeader(output[2])
self.assertNicelyFormattedTableRule(output[3])
self.assertNicelyFormattedTableData(output[4])
self.assertEqual(output[5].strip(), '')
self.assertNicelyFormattedTableHeader(output[1])
self.assertNicelyFormattedTableRule(output[2])
self.assertNicelyFormattedTableData(output[3])
self.assertEqual(output[4].strip(), '')
def test_color_output(self):
for termname in ('xterm', 'unknown-garbage'):
@ -275,9 +274,9 @@ class TestCqlshOutput(BaseTestCase):
# same query should show up as empty in cql 3
self.assertQueriesGiveColoredOutput((
(q, """
num | asciicol | bigintcol | blobcol | booleancol | datecol | decimalcol | doublecol | floatcol | intcol | textcol | timecol | timestampcol | uuidcol | varcharcol | varintcol
RRR MMMMMMMM MMMMMMMMM MMMMMMM MMMMMMMMMM MMMMMMM MMMMMMMMMM MMMMMMMMM MMMMMMMM MMMMMM MMMMMMM MMMMMMM MMMMMMMMMMMM MMMMMMM MMMMMMMMMM MMMMMMMMM
-----+----------+-----------+---------+------------+---------+------------+-----------+----------+--------+---------+---------+--------------+---------+------------+-----------
num | asciicol | bigintcol | blobcol | booleancol | decimalcol | doublecol | floatcol | intcol | textcol | timestampcol | uuidcol | varcharcol | varintcol
RRR MMMMMMMM MMMMMMMMM MMMMMMM MMMMMMMMMM MMMMMMMMMM MMMMMMMMM MMMMMMMM MMMMMM MMMMMMM MMMMMMMMMMMM MMMMMMM MMMMMMMMMM MMMMMMMMM
-----+----------+-----------+---------+------------+------------+-----------+----------+--------+---------+--------------+---------+------------+-----------
(0 rows)
@ -598,13 +597,11 @@ class TestCqlshOutput(BaseTestCase):
bigintcol bigint,
blobcol blob,
booleancol boolean,
datecol date,
decimalcol decimal,
doublecol double,
floatcol float,
intcol int,
textcol text,
timecol time,
timestampcol timestamp,
uuidcol uuid,
varcharcol text,

View File

@ -19,38 +19,37 @@ INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol
decimalcol, doublecol, floatcol, textcol,
timestampcol, uuidcol, varcharcol, varintcol)
VALUES (0, -12, 'abcdefg', 1234567890123456789, 0x000102030405fffefd, true,
19952.11882, 1.0, -2.1, 'Voilá!',
'2012-05-14 12:53:20+0000', bd1924e1-6af8-44ae-b5e1-f24131dbd460, '"', 10000000000000000000000000);
19952.11882, 1.0, -2.1, 'Voilá!', '2012-05-14 12:53:20+0000',
bd1924e1-6af8-44ae-b5e1-f24131dbd460, '"', 10000000000000000000000000);
INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol,
decimalcol, doublecol, floatcol, textcol,
timestampcol, uuidcol, varcharcol, varintcol)
VALUES (1, 2147483647, '__!''$#@!~"', 9223372036854775807, 0xffffffffffffffffff, true,
0.00000000000001, 9999999.999, 99999.99, '∭Ƕ⑮ฑ➳❏''',
'1900-01-01+0000', ffffffff-ffff-ffff-ffff-ffffffffffff, 'newline->
0.00000000000001, 9999999.999, 99999.99, '∭Ƕ⑮ฑ➳❏''', '1900-01-01+0000',
ffffffff-ffff-ffff-ffff-ffffffffffff, 'newline->
<-', 9);
INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol,
decimalcol, doublecol, floatcol, textcol,
timestampcol, uuidcol, varcharcol, varintcol)
VALUES (2, 0, '', 0, 0x, false,
0.0, 0.0, 0.0, '',
0, 00000000-0000-0000-0000-000000000000, '', 0);
0.0, 0.0, 0.0, '', 0,
00000000-0000-0000-0000-000000000000, '', 0);
INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol,
decimalcol, doublecol, floatcol, textcol,
timestampcol, uuidcol, varcharcol, varintcol)
VALUES (3, -2147483648, '''''''', -9223372036854775808, 0x80, false,
10.0000000000000, -1004.10, 100000000.9, '龍馭鬱',
'2038-01-19T03:14-1200', ffffffff-ffff-1fff-8fff-ffffffffffff,
'''', -10000000000000000000000000);
10.0000000000000, -1004.10, 100000000.9, '龍馭鬱', '2038-01-19T03:14-1200',
ffffffff-ffff-1fff-8fff-ffffffffffff, '''', -10000000000000000000000000);
INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol,
decimalcol, doublecol, floatcol, textcol,
timestampcol, uuidcol, varcharcol, varintcol)
VALUES (4, blobAsInt(0x), '', blobAsBigint(0x), 0x, blobAsBoolean(0x),
blobAsDecimal(0x), blobAsDouble(0x), blobAsFloat(0x), '',
blobAsTimestamp(0x), blobAsUuid(0x), '', blobAsVarint(0x));
VALUES (4, blobAsInt(0x), '', blobAsBigint(0x), 0x, blobAsBoolean(0x), blobAsDecimal(0x),
blobAsDouble(0x), blobAsFloat(0x), '', blobAsTimestamp(0x), blobAsUuid(0x), '',
blobAsVarint(0x));

View File

@ -38,24 +38,22 @@ public interface CQL3Type
public enum Native implements CQL3Type
{
ASCII (AsciiType.instance),
BIGINT (LongType.instance),
BLOB (BytesType.instance),
BOOLEAN (BooleanType.instance),
COUNTER (CounterColumnType.instance),
DECIMAL (DecimalType.instance),
DOUBLE (DoubleType.instance),
FLOAT (FloatType.instance),
INET (InetAddressType.instance),
INT (Int32Type.instance),
TEXT (UTF8Type.instance),
TIMESTAMP (TimestampType.instance),
UUID (UUIDType.instance),
VARCHAR (UTF8Type.instance),
VARINT (IntegerType.instance),
TIMEUUID (TimeUUIDType.instance),
DATE (SimpleDateType.instance),
TIME (TimeType.instance);
ASCII (AsciiType.instance),
BIGINT (LongType.instance),
BLOB (BytesType.instance),
BOOLEAN (BooleanType.instance),
COUNTER (CounterColumnType.instance),
DECIMAL (DecimalType.instance),
DOUBLE (DoubleType.instance),
FLOAT (FloatType.instance),
INET (InetAddressType.instance),
INT (Int32Type.instance),
TEXT (UTF8Type.instance),
TIMESTAMP(TimestampType.instance),
UUID (UUIDType.instance),
VARCHAR (UTF8Type.instance),
VARINT (IntegerType.instance),
TIMEUUID (TimeUUIDType.instance);
private final AbstractType<?> type;

View File

@ -44,7 +44,7 @@ public abstract class Constants
public enum Type
{
STRING, INTEGER, UUID, FLOAT, DATE, TIME, BOOLEAN, HEX;
STRING, INTEGER, UUID, FLOAT, BOOLEAN, HEX;
}
public static final Term.Raw NULL_LITERAL = new Term.Raw()
@ -179,8 +179,6 @@ public abstract class Constants
case TEXT:
case INET:
case VARCHAR:
case DATE:
case TIME:
case TIMESTAMP:
return true;
}
@ -190,7 +188,6 @@ public abstract class Constants
{
case BIGINT:
case COUNTER:
case DATE:
case DECIMAL:
case DOUBLE:
case FLOAT:

View File

@ -1161,8 +1161,6 @@ native_type returns [CQL3Type t]
| K_VARCHAR { $t = CQL3Type.Native.VARCHAR; }
| K_VARINT { $t = CQL3Type.Native.VARINT; }
| K_TIMEUUID { $t = CQL3Type.Native.TIMEUUID; }
| K_DATE { $t = CQL3Type.Native.DATE; }
| K_TIME { $t = CQL3Type.Native.TIME; }
;
collection_type returns [CQL3Type.Raw pt]
@ -1330,8 +1328,6 @@ K_VARINT: V A R I N T;
K_TIMEUUID: T I M E U U I D;
K_TOKEN: T O K E N;
K_WRITETIME: W R I T E T I M E;
K_DATE: D A T E;
K_TIME: T I M E;
K_NULL: N U L L;
K_NOT: N O T;

View File

@ -59,11 +59,6 @@ public final class IntegerType extends AbstractType<BigInteger>
IntegerType() {/* singleton */}
public int compare(ByteBuffer lhs, ByteBuffer rhs)
{
return IntegerType.compareIntegers(lhs, rhs);
}
public static int compareIntegers(ByteBuffer lhs, ByteBuffer rhs)
{
int lhsLen = lhs.remaining();
int rhsLen = rhs.remaining();

View File

@ -1,72 +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.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.SimpleDateSerializer;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
public class SimpleDateType extends AbstractType<Integer>
{
public static final SimpleDateType instance = new SimpleDateType();
SimpleDateType() {} // singleton
public int compare(ByteBuffer o1, ByteBuffer o2)
{
// We add Integer.MIN_VALUE to overflow to allow unsigned comparison
return ByteBufferUtil.compareUnsigned(o1, o2);
}
public boolean isByteOrderComparable()
{
return true;
}
public ByteBuffer fromString(String source) throws MarshalException
{
return ByteBufferUtil.bytes(SimpleDateSerializer.dateStringToDays(source));
}
@Override
public boolean isCompatibleWith(AbstractType<?> previous)
{
return super.isCompatibleWith(previous);
}
@Override
public boolean isValueCompatibleWithInternal(AbstractType<?> otherType)
{
return this == otherType || otherType == IntegerType.instance;
}
@Override
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.DATE;
}
public TypeSerializer<Integer> getSerializer()
{
return SimpleDateSerializer.instance;
}
}

View File

@ -1,72 +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.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.serializers.TimeSerializer;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
/**
* Nanosecond resolution time values
*/
public class TimeType extends AbstractType<Long>
{
public static final TimeType instance = new TimeType();
private TimeType() {} // singleton
public int compare(ByteBuffer o1, ByteBuffer o2)
{
return ByteBufferUtil.compareUnsigned(o1, o2);
}
public ByteBuffer fromString(String source) throws MarshalException
{
return decompose(TimeSerializer.timeStringToLong(source));
}
public boolean isByteOrderComparable()
{
return true;
}
@Override
public boolean isCompatibleWith(AbstractType<?> previous)
{
return super.isCompatibleWith(previous);
}
@Override
public boolean isValueCompatibleWithInternal(AbstractType<?> otherType)
{
return this == otherType || otherType == LongType.instance;
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.TIME;
}
public TypeSerializer<Long> getSerializer()
{
return TimeSerializer.instance;
}
}

View File

@ -1,117 +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.serializers;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.apache.cassandra.utils.ByteBufferUtil;
// For byte-order comparability, we shift by Integer.MIN_VALUE and treat the data as an unsigned integer ranging from
// min date to max date w/epoch sitting in the center @ 2^31
public class SimpleDateSerializer implements TypeSerializer<Integer>
{
private static final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd").withZone(DateTimeZone.UTC);
private static final long minSupportedDateMillis = TimeUnit.DAYS.toMillis(Integer.MIN_VALUE);
private static final long maxSupportedDateMillis = TimeUnit.DAYS.toMillis(Integer.MAX_VALUE);
private static final long maxSupportedDays = (long)Math.pow(2,32) - 1;
private static final long byteOrderShift = (long)Math.pow(2,31) * 2;
private static final Pattern rawPattern = Pattern.compile("^-?\\d+$");
public static final SimpleDateSerializer instance = new SimpleDateSerializer();
public Integer deserialize(ByteBuffer bytes)
{
return bytes.remaining() == 0 ? null : ByteBufferUtil.toInt(bytes);
}
public ByteBuffer serialize(Integer value)
{
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public static Integer dateStringToDays(String source) throws MarshalException
{
// Raw day value in unsigned int form, epoch @ 2^31
if (rawPattern.matcher(source).matches())
{
try
{
Long result = Long.parseLong(source);
if (result < 0 || result > maxSupportedDays)
throw new NumberFormatException("Input out of bounds: " + source);
// Shift > epoch days into negative portion of Integer result for byte order comparability
if (result >= Integer.MAX_VALUE)
result -= byteOrderShift;
return result.intValue();
}
catch (NumberFormatException e)
{
throw new MarshalException(String.format("Unable to make unsigned int (for date) from: '%s'", source), e);
}
}
// Attempt to parse as date string
try
{
DateTime parsed = formatter.parseDateTime(source);
long millis = parsed.getMillis();
if (millis < minSupportedDateMillis)
throw new MarshalException(String.format("Input date %s is less than min supported date %s", source, new LocalDate(minSupportedDateMillis).toString()));
if (millis > maxSupportedDateMillis)
throw new MarshalException(String.format("Input date %s is greater than max supported date %s", source, new LocalDate(maxSupportedDateMillis).toString()));
Integer result = (int)TimeUnit.MILLISECONDS.toDays(millis);
result -= Integer.MIN_VALUE;
return result;
}
catch (IllegalArgumentException e1)
{
throw new MarshalException(String.format("Unable to coerce '%s' to a formatted date (long)", source), e1);
}
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 4)
throw new MarshalException(String.format("Expected 4 byte long for date (%d)", bytes.remaining()));
}
public String toString(Integer value)
{
if (value == null)
return "";
return formatter.print(new LocalDate(TimeUnit.DAYS.toMillis(value - Integer.MIN_VALUE), DateTimeZone.UTC));
}
public Class<Integer> getType()
{
return Integer.class;
}
}

View File

@ -1,198 +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.serializers;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.apache.cassandra.utils.ByteBufferUtil;
public class TimeSerializer implements TypeSerializer<Long>
{
public static final Pattern timePattern = Pattern.compile("^-?\\d+$");
public static final TimeSerializer instance = new TimeSerializer();
public Long deserialize(ByteBuffer bytes)
{
return bytes.remaining() == 0 ? null : ByteBufferUtil.toLong(bytes);
}
public ByteBuffer serialize(Long value)
{
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public static Long timeStringToLong(String source) throws MarshalException
{
// nano since start of day, raw
if (timePattern.matcher(source).matches())
{
try
{
Long result = Long.parseLong(source);
if (result < 0 || result > TimeUnit.DAYS.toNanos(1))
throw new NumberFormatException("Input long out of bounds: " + source);
return result;
}
catch (NumberFormatException e)
{
throw new MarshalException(String.format("Unable to make long (for time) from: '%s'", source), e);
}
}
// Last chance, attempt to parse as time string
try
{
return parseTimeStrictly(source);
}
catch (IllegalArgumentException e1)
{
throw new MarshalException(String.format("(TimeType) Unable to coerce '%s' to a formatted time (long)", source), e1);
}
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8)
throw new MarshalException(String.format("Expected 8 byte long for time (%d)", bytes.remaining()));
}
public String toString(Long value)
{
if (value == null)
return "null";
int nano = (int)(value % 1000);
value -= nano;
value /= 1000;
int micro = (int)(value % 1000);
value -= micro;
value /= 1000;
int milli = (int)(value % 1000);
value -= milli;
value /= 1000;
int seconds = (int)(value % 60);
value -= seconds;
value /= 60;
int minutes = (int)(value % 60);
value -= minutes;
value /= 60;
int hours = (int)(value % 24);
value -= hours;
value /= 24;
assert(value == 0);
StringBuilder sb = new StringBuilder();
leftPadZeros(hours, 2, sb);
sb.append(":");
leftPadZeros(minutes, 2, sb);
sb.append(":");
leftPadZeros(seconds, 2, sb);
sb.append(".");
leftPadZeros(milli, 3, sb);
leftPadZeros(micro, 3, sb);
leftPadZeros(nano, 3, sb);
return sb.toString();
}
private void leftPadZeros(int value, int digits, StringBuilder sb)
{
for (int i = 1; i < digits; ++i)
{
if (value < Math.pow(10, i))
sb.append("0");
}
sb.append(value);
}
public Class<Long> getType()
{
return Long.class;
}
// Time specific parsing loosely based on java.sql.Timestamp
private static Long parseTimeStrictly(String s) throws IllegalArgumentException
{
String nanos_s;
long hour;
long minute;
long second;
long a_nanos = 0;
int firstColon = 0;
int secondColon = 0;
int period = 0;
String formatError = "Timestamp format must be hh:mm:ss[.fffffffff]";
String zeros = "000000000";
if (s == null)
throw new java.lang.IllegalArgumentException(formatError);
s = s.trim();
// Parse the time
firstColon = s.indexOf(':');
secondColon = s.indexOf(':', firstColon+1);
period = s.indexOf('.', secondColon+1);
// Convert the time; default missing nanos
if (firstColon > 0 && secondColon > 0 && secondColon < s.length() - 1)
{
hour = Integer.parseInt(s.substring(0, firstColon));
if (hour < 0 || hour >= 24)
throw new IllegalArgumentException("Hour out of bounds.");
minute = Integer.parseInt(s.substring(firstColon + 1, secondColon));
if (minute < 0 || minute >= 60)
throw new IllegalArgumentException("Minute out of bounds.");
if (period > 0 && period < s.length() - 1)
{
second = Integer.parseInt(s.substring(secondColon + 1, period));
if (second < 0 || second >= 60)
throw new IllegalArgumentException("Second out of bounds.");
nanos_s = s.substring(period + 1);
if (nanos_s.length() > 9)
throw new IllegalArgumentException(formatError);
if (!Character.isDigit(nanos_s.charAt(0)))
throw new IllegalArgumentException(formatError);
nanos_s = nanos_s + zeros.substring(0, 9 - nanos_s.length());
a_nanos = Integer.parseInt(nanos_s);
}
else if (period > 0)
throw new IllegalArgumentException(formatError);
else
{
second = Integer.parseInt(s.substring(secondColon + 1));
if (second < 0 || second >= 60)
throw new IllegalArgumentException("Second out of bounds.");
}
}
else
throw new IllegalArgumentException(formatError);
long rawTime = 0;
rawTime += TimeUnit.HOURS.toNanos(hour);
rawTime += TimeUnit.MINUTES.toNanos(minute);
rawTime += TimeUnit.SECONDS.toNanos(second);
rawTime += a_nanos;
return rawTime;
}
}

View File

@ -35,4 +35,3 @@ public interface TypeSerializer<T>
public Class<T> getType();
}

View File

@ -49,8 +49,6 @@ public enum DataType implements OptionCodec.Codecable<DataType>
VARINT (14, IntegerType.instance),
TIMEUUID (15, TimeUUIDType.instance),
INET (16, InetAddressType.instance),
DATE (17, DateType.instance),
TIME (18, TimeType.instance),
LIST (32, null),
MAP (33, null),
SET (34, null),

View File

@ -1,153 +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.db.marshal;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.apache.cassandra.serializers.SimpleDateSerializer;
public class SimpleDateTypeTest
{
@Test public void TestComparison()
{
ByteBuffer d1 = SimpleDateType.instance.fromString("1970-01-05");
ByteBuffer d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(4));
assert SimpleDateType.instance.compare(d1, d2) == 0 : "Failed == comparison";
String.format("Failed == comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1970-01-05");
d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(10));
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed comparison of %s and %s, expected <",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1970-01-05"); // 4
d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(-10));
assert SimpleDateType.instance.compare(d1, d2) > 0 :
String.format("Failed comparison of %s and %s, expected > 0",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1");
d2 = SimpleDateType.instance.fromString("1000");
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed < comparison with string inputs %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
Integer intLimit = Integer.MAX_VALUE;
d1 = SimpleDateType.instance.fromString("0");
d2 = SimpleDateType.instance.fromString(intLimit.toString());
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed < comparison with string inputs at integer bounds %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
Long overLimit = (long)(Integer.MAX_VALUE);
d1 = SimpleDateType.instance.fromString("0");
d2 = SimpleDateType.instance.fromString(overLimit.toString());
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed < comparison with string inputs at integer bounds %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
Long i1 = 0L;
Long i2 = (long)Math.pow(2,32) - 1;
d1 = SimpleDateType.instance.fromString(i1.toString());
d2 = SimpleDateType.instance.fromString(i2.toString());
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed limits comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("256");
d2 = SimpleDateType.instance.fromString("512");
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateSerializer.instance.serialize(makeUnsigned(0));
d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(Integer.MAX_VALUE));
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed neg/pos comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("-10000-10-10");
d2 = SimpleDateType.instance.fromString("10000-10-10");
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed neg/pos string comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1969-12-31");
d2 = SimpleDateType.instance.fromString("1970-1-1");
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed pre/post epoch comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1970-1-1");
d2 = SimpleDateType.instance.fromString("1970-1-1");
assert SimpleDateType.instance.compare(d1, d2) == 0 :
String.format("Failed == date from string comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
d1 = SimpleDateType.instance.fromString("1970-1-1");
d2 = SimpleDateType.instance.fromString("1970-1-2");
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed post epoch string comparison with %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
for (int i = 0; i < 32; ++i)
{
int offset = (int)Math.pow(2,i);
d1 = SimpleDateSerializer.instance.serialize(makeUnsigned(0 - offset));
d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(offset));
assert SimpleDateType.instance.compare(d1, d2) < 0 :
String.format("Failed < comparison of %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
}
for (int i = 0; i < 32; ++i)
{
int offset = (int)Math.pow(2,i);
d1 = SimpleDateSerializer.instance.serialize(makeUnsigned(offset));
d2 = SimpleDateSerializer.instance.serialize(makeUnsigned(0 - offset));
assert SimpleDateType.instance.compare(d1, d2) > 0 :
String.format("Failed > comparison of %s and %s",
SimpleDateSerializer.instance.deserialize(d1),
SimpleDateSerializer.instance.deserialize(d2));
}
}
private Integer makeUnsigned(int input)
{
return input - Integer.MIN_VALUE;
}
}

View File

@ -1,61 +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.db.marshal;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.apache.cassandra.serializers.TimeSerializer;
public class TimeTypeTest
{
@Test public void TestComparison()
{
Long t1 = TimeSerializer.timeStringToLong("01:00:00.123456789");
Long t2 = new Long((1L * 60L * 60L * 1000L * 1000L * 1000L) + 123456789);
ByteBuffer b1 = TimeSerializer.instance.serialize(t1);
ByteBuffer b2 = TimeSerializer.instance.serialize(t2);
assert TimeType.instance.compare(b1, b2) == 0 : "Failed == comparison";
b2 = TimeSerializer.instance.serialize(123456789L);
assert TimeType.instance.compare(b1, b2) > 0 : "Failed > comparison";
t2 = new Long(2L * 60L * 60L * 1000L * 1000L * 1000L + 123456789);
b2 = TimeSerializer.instance.serialize(t2);
assert TimeType.instance.compare(b1, b2) < 0 : "Failed < comparison";
b1 = TimeSerializer.instance.serialize(0L);
b2 = TimeSerializer.instance.serialize(0L);
assert TimeType.instance.compare(b1, b2) == 0 : "Failed == comparison on 0";
b1 = TimeSerializer.instance.serialize(0L);
b2 = TimeSerializer.instance.serialize(10000000L);
assert TimeType.instance.compare(b1, b2) == -1 : "Failed < comparison on 0";
b1 = TimeSerializer.instance.serialize(0L);
b2 = TimeSerializer.instance.serialize(TimeUnit.DAYS.toNanos(1));
assert TimeType.instance.compare(b1, b2) == -1 : "Failed < comparison against max range.";
b1 = TimeSerializer.instance.serialize(TimeUnit.DAYS.toNanos(1));
b2 = TimeSerializer.instance.serialize(0L);
assert TimeType.instance.compare(b1, b2) == 1 : "Failed > comparison against max range.";
}
}

View File

@ -1,155 +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.serializers;
import org.apache.cassandra.db.marshal.SimpleDateType;
import org.apache.cassandra.utils.Pair;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
public class SimpleDateSerializerTest
{
private static final long millisPerDay = 1000 * 60 * 60 * 24;
private String dates[] = new String[]
{
"1970-01-01",
"1970-01-02",
"1969-12-31",
"-0001-01-02",
"-5877521-01-02",
"2014-01-01",
"5881580-01-10",
"1920-12-01",
"1582-10-19"
};
private static GregorianCalendar testCalendar = new GregorianCalendar();
private static SimpleDateFormat dateFormatUTC = new SimpleDateFormat("yyyy-MM-dd");
{
testCalendar.setGregorianChange(new Date(Long.MIN_VALUE));
testCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
dateFormatUTC.setCalendar(testCalendar);
dateFormatUTC.setLenient(false);
}
@Test
public void testDateStringToTimestamp()
{
List<String> unparsedDates = new ArrayList<>();
List<String> badParseResults = new ArrayList<>();
for (String date : dates)
{
try
{
Integer days = SimpleDateSerializer.dateStringToDays(date);
ByteBuffer value = SimpleDateSerializer.instance.serialize(days);
Integer deserialized = SimpleDateSerializer.instance.deserialize(value);
String toStringValue = SimpleDateSerializer.instance.toString(deserialized);
if (!date.equals(toStringValue)) {
badParseResults.add(String.format("Failed to parse date correctly. Expected %s, got %s\n", date, toStringValue));
}
}
catch (MarshalException e)
{
System.err.println("Got an exception: " + e);
unparsedDates.add(date);
}
}
assert unparsedDates.isEmpty() : "Unable to parse: " + unparsedDates;
assert badParseResults.isEmpty() : "Incorrect parse results: " + badParseResults;
}
@Test
public void testDaysStringToInt()
{
Integer value = SimpleDateSerializer.dateStringToDays("12345");
assert value.compareTo(12345) == 0 : String.format("Failed to parse integer based date. Expected %s, got %s",
12345,
value);
}
@Test
public void testProlepticRange()
{
for (int i = 1; i < 31; ++i)
{
String date = "1582-10-";
if (i < 10) date += "0";
date += i;
Integer days = SimpleDateSerializer.dateStringToDays(date);
ByteBuffer value = SimpleDateType.instance.fromString(days.toString());
Integer deserialized = SimpleDateSerializer.instance.deserialize(value);
// Serialized values are unsigned int, unwrap bits w/overflow
deserialized -= Integer.MIN_VALUE;
Timestamp ts = new Timestamp(deserialized * millisPerDay);
testCalendar.setTime(ts);
Date newDate = testCalendar.getTime();
assert (dateFormatUTC.format(newDate)).equals(date) :
String.format("Expected [%s], got [%s]", date, dateFormatUTC.format(newDate).toString());
}
}
@Test (expected=MarshalException.class)
public void testOutOfBoundsLow()
{
Integer days = SimpleDateSerializer.dateStringToDays(new Date(Integer.MIN_VALUE * millisPerDay - millisPerDay).toString());
}
@Test (expected=MarshalException.class)
public void testOutOfBoundsHigh()
{
Integer days = SimpleDateSerializer.dateStringToDays(new Date(Integer.MAX_VALUE * millisPerDay + millisPerDay).toString());
}
@Test (expected=MarshalException.class)
public void testBadInput()
{
Integer days = SimpleDateSerializer.dateStringToDays("12A-01-01");
}
@Test (expected=MarshalException.class)
public void testBadMonth()
{
Integer days = SimpleDateSerializer.dateStringToDays("1000-13-01");
}
@Test (expected=MarshalException.class)
public void testBadDay()
{
Integer days = SimpleDateSerializer.dateStringToDays("1000-12-32");
}
@Test (expected=MarshalException.class)
public void testBadDayToMonth()
{
Integer days = SimpleDateSerializer.dateStringToDays("1000-09-31");
}
}

View File

@ -1,242 +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.serializers;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
public class TimeSerializerTest
{
@Test
public void testSerializerFromString()
{
// nano
long expected = 5;
Long time = TimeSerializer.timeStringToLong("00:00:00.000000005");
assert time == expected : String.format("Failed nano conversion. Expected %s, got %s", expected, time);
// usec
expected = TimeUnit.MICROSECONDS.toNanos(123);
time = TimeSerializer.timeStringToLong("00:00:00.000123000");
assert time == expected : String.format("Failed usec conversion. Expected %s, got %s", expected, time);
// milli
expected = TimeUnit.MILLISECONDS.toNanos(123);
time = TimeSerializer.timeStringToLong("00:00:00.123000");
assert time == expected : String.format("Failed milli conversion. Expected %s, got %s", expected, time);
// sec
expected = TimeUnit.SECONDS.toNanos(15);
time = TimeSerializer.timeStringToLong("00:00:15.000");
assert time == expected : String.format("Failed sec conversion. Expected %s, got %s", expected, time);
// min
expected = TimeUnit.MINUTES.toNanos(13);
time = TimeSerializer.timeStringToLong("00:13:00.000");
assert time == expected : String.format("Failed min conversion. Expected %s, got %s", expected, time);
// hour
expected = TimeUnit.HOURS.toNanos(2);
time = TimeSerializer.timeStringToLong("02:0:00.000");
assert time == expected : String.format("Failed min conversion. Expected %s, got %s", expected, time);
// complex
expected = buildExpected(4, 31, 12, 123, 456, 789);
time = TimeSerializer.timeStringToLong("4:31:12.123456789");
assert time == expected : String.format("Failed complex conversion. Expected %s, got %s", expected, time);
// upper bound
expected = buildExpected(23, 59, 59, 999, 999, 999);
time = TimeSerializer.timeStringToLong("23:59:59.999999999");
assert time == expected : String.format("Failed upper bounds conversion. Expected %s, got %s", expected, time);
// Test partial nano
expected = buildExpected(12, 13, 14, 123, 654, 120);
time = TimeSerializer.timeStringToLong("12:13:14.12365412");
assert time == expected : String.format("Failed partial nano timestring. Expected %s, got %s", expected, time);
// Test raw long value
expected = 10;
time = TimeSerializer.timeStringToLong("10");
assert time == expected : String.format("Failed long conversion. Expected %s, got %s", expected, time);
// Test 0 long
expected = 0;
time = TimeSerializer.timeStringToLong("0");
assert time == expected : String.format("Failed long conversion. Expected %s, got %s", expected, time);
}
private long buildExpected(int hour, int minute, int second, int milli, int micro, int nano)
{
return TimeUnit.HOURS.toNanos(hour) +
TimeUnit.MINUTES.toNanos(minute) +
TimeUnit.SECONDS.toNanos(second) +
TimeUnit.MILLISECONDS.toNanos(milli) +
TimeUnit.MICROSECONDS.toNanos(micro) +
nano;
}
@Test
public void testSerializerToString()
{
String source = "00:00:00.000000011";
Long time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "00:00:00.000012311";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "00:00:00.123000000";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "00:00:12.123450000";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "00:34:12.123450000";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "15:00:12.123450000";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
// boundaries
source = "00:00:00.000000000";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
source = "23:59:59.999999999";
time = TimeSerializer.timeStringToLong(source);
assert(source.equals(TimeSerializer.instance.toString(time)));
// truncated
source = "01:14:18.12";
time = TimeSerializer.timeStringToLong(source);
String result = TimeSerializer.instance.toString(time);
assert(result.equals("01:14:18.120000000"));
source = "01:14:18.1201";
time = TimeSerializer.timeStringToLong(source);
result = TimeSerializer.instance.toString(time);
assert(result.equals("01:14:18.120100000"));
source = "01:14:18.1201098";
time = TimeSerializer.timeStringToLong(source);
result = TimeSerializer.instance.toString(time);
assert(result.equals("01:14:18.120109800"));
}
@Test public void testSerialization()
{
String source = "01:01:01.123123123";
Long nt = TimeSerializer.timeStringToLong(source);
ByteBuffer buf = TimeSerializer.instance.serialize(nt);
TimeSerializer.instance.validate(buf);
Long result = TimeSerializer.instance.deserialize(buf);
String strResult = TimeSerializer.instance.toString(result);
assert(strResult.equals(source));
}
@Test (expected=MarshalException.class)
public void testBadHourLow()
{
Long time = TimeSerializer.timeStringToLong("-1:0:0.123456789");
}
@Test (expected=MarshalException.class)
public void testBadHourHigh()
{
Long time = TimeSerializer.timeStringToLong("24:0:0.123456789");
}
@Test (expected=MarshalException.class)
public void testBadMinuteLow()
{
Long time = TimeSerializer.timeStringToLong("23:-1:0.123456789");
}
@Test (expected=MarshalException.class)
public void testBadMinuteHigh()
{
Long time = TimeSerializer.timeStringToLong("23:60:0.123456789");
}
@Test (expected=MarshalException.class)
public void testEmpty()
{
Long time = TimeSerializer.timeStringToLong("");
}
@Test (expected=MarshalException.class)
public void testBadSecondLow()
{
Long time = TimeSerializer.timeStringToLong("23:59:-1.123456789");
}
@Test (expected=MarshalException.class)
public void testBadSecondHigh()
{
Long time = TimeSerializer.timeStringToLong("23:59:60.123456789");
}
@Test (expected=MarshalException.class)
public void testBadSecondHighNoMilli()
{
Long time = TimeSerializer.timeStringToLong("23:59:60");
}
@Test (expected=MarshalException.class)
public void testBadNanoLow()
{
Long time = TimeSerializer.timeStringToLong("23:59:59.-123456789");
}
@Test (expected=MarshalException.class)
public void testBadNanoHigh()
{
Long time = TimeSerializer.timeStringToLong("23:59:59.1234567899");
}
@Test (expected=MarshalException.class)
public void testBadNanoCharacter()
{
Long time = TimeSerializer.timeStringToLong("23:59:59.12345A789");
}
@Test (expected=MarshalException.class)
public void testNegativeLongTime()
{
Long time = TimeSerializer.timeStringToLong("-10");
}
@Test (expected=MarshalException.class)
public void testRawLongOverflow()
{
Long input = TimeUnit.DAYS.toNanos(1) + 1;
Long time = TimeSerializer.timeStringToLong(input.toString());
}
}