Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix time encoding to work with Cassandra 4 #269

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Roguelazer
Copy link
Contributor

The default Ruby .to_s method for a Time results in output of %Y-%m-%d %H:%M:%S %z; note the space between the seconds and the time offset.

In Cassandra 4.0, the validator for the TIMESTAMP column type is stricter and there cannot be a space between the fractional part and the timezone offset and it must match the format yyyy-mm-dd[(T| )HH:MM:SS[.fff]][(+|-)NNNN].

@Roguelazer Roguelazer changed the title fix time encoding fix time encoding to work with Cassandra 4 Sep 16, 2021
@absurdfarce absurdfarce self-assigned this Oct 14, 2021
@absurdfarce absurdfarce self-requested a review October 14, 2021 22:15
@absurdfarce
Copy link
Contributor

absurdfarce commented Oct 15, 2021

Hey @Roguelazer, thanks (again) for the PR!

Do you happen to have some sample code that you can share which exercises this issue? I ask because it looks like you're trying to call Cassandra::Utils.encode_time with a Ruby Time object with the expectation that you'll get something out that can be inserted into a column of timestamp type. The problem is that the driver tries to encode Time objects via encode_timestamp while encode_time is reserved for Cassandra::Time (https://github.com/datastax/ruby-driver/blob/master/lib/cassandra/util.rb#L94-L115). So you wind up with the following behaviour here:

[mersault@linux ruby]$ irb
2.5.1 :001 > require 'cassandra'
 => true
2.5.1 :002 > Cassandra::Util.encode_timestamp(Time.now)
 => "1634273394"
2.5.1 :003 > Cassandra::Util.encode_time(Time.now)
 => "'2021-10-14 23:49:54 -0500'"
2.5.1 :004 > Cassandra::Util.encode_object(Time.now)
 => "1634273394"
2.5.1 :005 > Cassandra::Util.encode_timestamp(Cassandra::Time.new(1000000000 * 300))
Traceback (most recent call last):
        3: from /home/mersault/.rvm/rubies/ruby-2.5.1/bin/irb:11:in `<main>'
        2: from (irb):5
        1: from /home/mersault/.rvm/gems/ruby-2.5.1@countapp/gems/cassandra-driver-3.2.5/lib/cassandra/util.rb:127:in `encode_timestamp'
NoMethodError (undefined method `to_i' for #<Cassandra::Time:0x00000000031dcf88 @nanoseconds=300000000000>)
Did you mean?  to_s
2.5.1 :006 > Cassandra::Util.encode_time(Cassandra::Time.new(1000000000 * 300))
 => "'00:05:00.000'"
2.5.1 :007 > Cassandra::Util.encode_object(Cassandra::Time.new(1000000000 * 300))
 => "'00:05:00.000'"

Given that a Ruby top-level Time object maps to a "timestamp" CQL type while Cassandra::Time maps to a "time" type I'd expect that given the following:

CREATE KEYSPACE foo WITH REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1};
CREATE TABLE foo.bar (key int PRIMARY KEY, ts timestamp);

this code should work without issue:

require 'cassandra'
require 'cassandra/util'
require 'time'

cluster = Cassandra.cluster
session = cluster.connect
stmt = session.prepare "insert into foo.bar (key,ts) values (?,?)"
session.execute stmt, arguments: [1, Time.now]

And indeed that's exactly what I get; the code runs without an error of any kind and after execution I observe the following:

cqlsh> select * from foo.bar;                                                                                                                                                    

 key | ts
-----+---------------------------------
   1 | 2021-10-15 05:30:53.477000+0000

(1 rows)

That's with Ruby 2.5.1 (using cassandra-driver 3.2.5) against Cassandra 4.0.0.

Please let me know if I've misunderstood something about your use case @Roguelazer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants