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

Catch HOUR_OF_DAY error #1160

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,39 @@ protected IRubyObject timeToRuby(final ThreadContext context,
return DateTimeUtils.newDummyTime(context, value, getDefaultTimeZone(context));
}

@Override
protected IRubyObject timestampToRuby(final ThreadContext context,
final Ruby runtime, final ResultSet resultSet, final int column)
throws SQLException {

final Timestamp value;
try {
value = resultSet.getTimestamp(column);
}
catch (SQLException e) {
if (e.getMessage().contains("HOUR_OF_DAY")) {
return stringToRuby(context, runtime, resultSet, column);
}
else {
throw e;
}
}
if ( value == null ) {
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
}

if ( rawDateTime != null && rawDateTime) {
return RubyString.newString(runtime, DateTimeUtils.timestampToString(value));
}

// NOTE: with 'raw' String AR's Type::DateTime does put the time in proper time-zone
// while when returning a Time object it just adjusts usec (apply_seconds_precision)
// yet for custom SELECTs to work (SELECT created_at ... ) and for compatibility we
// should be returning Time (by default) - AR does this by adjusting mysql2/pg returns

return DateTimeUtils.newTime(context, value, getDefaultTimeZone(context));
}

@Override
protected IRubyObject streamToRuby(final ThreadContext context,
final Ruby runtime, final ResultSet resultSet, final int column)
Expand Down
8 changes: 0 additions & 8 deletions test/db/mysql/simple_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,6 @@ def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timez
super
end

# @override
def test_time_with_default_timezone_local
if ENV['CI']
pend 'TODO: CI: when we start off with UTC the MySQL driver does not handle the time-zone switch right'
end
super
end

# NOTE: all of the above pends are not crucial
# we're really pushing the limits with switching TZ in the system ... esp. for the MySQL driver

Expand Down
10 changes: 10 additions & 0 deletions test/db/postgresql/simple_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ def test_big_decimal
end
end

if Time.respond_to?(:zone)
# @override
def test_time_in_dst_change_hour_local
if ENV['CI']
pend 'TODO: CI: with AR default timezone set to :local PostgreSQL driver will not convert DST missing hour time'
end
super
end
end

def test_encoding
assert_not_nil connection.encoding
end
Expand Down
37 changes: 37 additions & 0 deletions test/simple.rb
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,44 @@ def test_time_with_default_timezone_local
end
end
end
end

def test_time_in_dst_change_hour_utc
skip "with_system_tz not working in tomcat" if ActiveRecord::Base.connection.raw_connection.jndi?

with_system_tz 'Europe/Prague' do
Time.use_zone 'Europe/Prague' do
with_timezone_config default: :utc do
id = DbType.connection.insert(
"INSERT INTO db_types (sample_datetime)
values ('2024-03-31 02:30:00')"
)
saved_time = DbType.find(id).sample_datetime

assert_equal Time.utc(2024, 3, 31, 2, 30), saved_time
assert_equal 'UTC', saved_time.zone
end
end
end
end

def test_time_in_dst_change_hour_local
skip "with_system_tz not working in tomcat" if ActiveRecord::Base.connection.raw_connection.jndi?

with_system_tz 'Europe/Prague' do
Time.use_zone 'Europe/Prague' do
with_timezone_config default: :local do
id = DbType.connection.insert(
"INSERT INTO db_types (sample_datetime)
values ('2024-03-31 02:30:00')"
)
saved_time = DbType.find(id).sample_datetime

assert_equal Time.local(2024, 3, 31, 3, 30), saved_time
assert_not_equal 'UTC', saved_time.zone
end
end
end
end

#
Expand Down
7 changes: 7 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,18 @@ def with_java_tz(new_tz)
java.util.TimeZone.setDefault new_tz
org.joda.time.DateTimeZone.setDefault org.joda.time.DateTimeZone.forTimeZone(new_tz)
java.lang.System.setProperty 'user.timezone', new_tz.getID
connection_properties = ActiveRecord::Base.remove_connection
prev_config = connection_properties.configuration_hash
new_config = prev_config.deep_dup
new_config[:properties] ||= {}
new_config[:properties]['serverTimezone'] = new_tz.getID
ActiveRecord::Base.establish_connection new_config
yield
ensure
java.util.TimeZone.setDefault old_tz
org.joda.time.DateTimeZone.setDefault old_jd
old_user_tz ? java.lang.System.setProperty('user.timezone', old_user_tz) : java.lang.System.clearProperty('user.timezone')
ActiveRecord::Base.establish_connection prev_config
end
end

Expand Down
Loading