JRuby - query result is converted to String instead of Date

110 views Asked by At
activerecord 4.2.11.1
activerecord-jdbc-adapter 1.3.25
activerecord-jdbcpostgresql-adapter 1.3.25
jdbc-postgres 9.4.1206

The following method call returns a Date when using ruby 2.3.3 but returns a String when using JRuby-9.1.17.0 with activerecord-jdbcpostgresql-adapter :

2.3.3 :017 > Table.select('now() as date').first.date
  Table Load (0.7ms)  SELECT  now() as date FROM "tables"  ORDER BY "tables"."id" ASC LIMIT 1
 => 2019-05-17 03:46:52 UTC 
jruby-9.1.17.0 :002 > Table.select('now() as date').first.date
  Table Load (2.0ms)  SELECT  now() as date FROM "tables"  ORDER BY "tables"."id" ASC LIMIT 1
 => "2019-05-17 03:48:57.572526+00" 

This only happens if the selected attribute does not exist in the database:

2.3.3 :012 > Table.select(:created_at).first.created_at
  Table Load (0.6ms)  SELECT  "tables"."created_at" FROM "tables"  ORDER BY "tables"."id" ASC LIMIT 1
 => Wed, 25 Sep 2013 14:26:17 -03 -03:00 
jruby-9.1.17.0 :019 > Table.select(:created_at).first.created_at
  Table Load (0.8ms)  SELECT  "tables"."created_at" FROM "tables"  ORDER BY "tables"."id" ASC LIMIT 1
 => Wed, 25 Sep 2013 14:26:17 -03 -03:00 

This happens with either WebRick or Tomcat 7. This error does not occur with the same version of activerecord-jdbc-adapter if using Active Record 4.0 or 4.1. Upgrading to latest jruby-9.2.7.0 did not help either.

2

There are 2 answers

3
kares On

seems like a compatibility bug in AR-JDBC, at this point likely a won't fix as AR 4.2 also isn't supported.

you should try upgrading to 5.x if this is an issue or try resolving the problem and submit a PR ...

as a last resort try setting ActiveRecord::ConnectionAdapters::JdbcConnection.raw_date_time = true (altough I think its already truewhen running on AR 4.2)

0
Gus On

as @kares noted, this look like a bug, also it is related to the configuration ActiveRecord::ConnectionAdapters::JdbcConnection.raw_date_time. Its seems like if it is set to true the method call below returns a String, otherwise it returns a Time instance:

Locatario.select('now() as date').first.date

I have checked this behaviour with 3 versions of active_record:

Rails 3.2
    default raw_date_time? == true
    Table.select('now() as date').first.date
        Ruby: returns String
        JRuby: returns String
Rails 4.0/4.1
    default raw_date_time? == nil
    Table.select('now() as date').first.date
        Ruby: returns Time
        JRuby: returns Time
Rails 4.2
    default raw_date_time? == true
    Table.select('now() as date').first.date
        Ruby: returns Time
        JRuby: returns String

So, it looks like to emulate active_record >= 4.0 the gem activerecord-jdbc-adapter should use raw_date_time = false, because it should return a Time instance with the method call in question. As a workaround I created a file with the following content under initializers:

if RUBY_PLATFORM == "java" && Rails::VERSION::STRING.starts_with?("4.2.") 
    ActiveRecord::ConnectionAdapters::JdbcConnection.raw_date_time = false
end