Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def sp_executesql_types_and_parameters(binds)
types, params = [], []
binds.each_with_index do |attr, index|
types << "@#{index} #{sp_executesql_sql_type(attr)}"
params << type_cast(attr.value_for_database)
params << sp_executesql_sql_param(attr)
end
[types, params]
end
Expand All @@ -250,9 +250,20 @@ def sp_executesql_sql_type(attr)
case value = attr.value_for_database
when Numeric
'int'.freeze
when String
'nvarchar(max)'.freeze
else
raise TypeError, "sp_executesql_sql_type can not find sql type for attr #{attr.inspect}"
quote(value)
end
end

def sp_executesql_sql_param(attr)
case attr.value_for_database
when Type::Binary::Data,
ActiveRecord::Type::SQLServer::Data
quote(attr.value_for_database)
else
quote(type_cast(attr.value_for_database))
end
end

Expand Down
13 changes: 3 additions & 10 deletions lib/active_record/connection_adapters/sqlserver/quoting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,10 @@ def _quote(value)

def _type_cast(value)
case value
when nil
"NULL"
when Symbol
_quote(value.to_s)
when String, ActiveSupport::Multibyte::Chars
_quote(value)
when Type::Binary::Data
_quote(value)
when ActiveRecord::Type::SQLServer::Data
_quote(value)
else super
value.to_s
else
super
end
end

Expand Down
4 changes: 4 additions & 0 deletions lib/active_record/connection_adapters/sqlserver/type/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ def to_s
end
alias_method :to_str, :to_s

def inspect
@value.inspect
end

end
end
end
Expand Down
22 changes: 16 additions & 6 deletions lib/active_record/connection_adapters/sqlserver/type/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,32 @@ def sqlserver_type

def serialize(value)
return unless value.present?
return value if value.is_a?(Data)
Data.new super, self
date = value.to_s(:_sqlserver_dateformat)
Data.new date, self
end

def deserialize(value)
return value.value if value.is_a?(Data)
super
value.is_a?(Data) ? super(value.value) : super
end

def type_cast_for_schema(value)
serialize(value).quoted
end

def quoted(value)
date = value.to_s(:_sqlserver_dateformat)
Utils.quote_string_single(date)
Utils.quote_string_single(value)
end

private

def fast_string_to_date(string)
::Date.strptime(string, fast_string_to_date_format)
rescue ArgumentError
super
end

def fast_string_to_date_format
::Date::DATE_FORMATS[:_sqlserver_dateformat]
end

end
Expand Down
32 changes: 19 additions & 13 deletions lib/active_record/connection_adapters/sqlserver/type/datetime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,23 @@ def sqlserver_type

def serialize(value)
return super unless value.acts_like?(:time)
Data.new super, self
datetime = super.to_s(:_sqlserver_datetime).tap do |v|
fraction = quote_fractional(value)
v << ".#{fraction}" unless fraction.to_i.zero?
end
Data.new datetime, self
end

def deserialize(value)
datetime = value.is_a?(Data) ? value.value : super
return unless datetime
zone_conversion(datetime)
value.is_a?(Data) ? super(value.value) : super
end

def type_cast_for_schema(value)
serialize(value).quoted
end

def quoted(value)
datetime = value.to_s(:_sqlserver_datetime)
datetime = "#{datetime}".tap do |v|
fraction = quote_fractional(value)
v << ".#{fraction}" unless fraction.to_i.zero?
end
Utils.quote_string_single(datetime)
Utils.quote_string_single(value)
end

private
Expand All @@ -42,9 +39,18 @@ def cast_value(value)
apply_seconds_precision(value)
end

def zone_conversion(value)
method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
value.respond_to?(method) ? value.send(method) : value
def fast_string_to_time(string)
fast_string_to_time_zone.strptime(string, fast_string_to_time_format).time
rescue ArgumentError
super
end

def fast_string_to_time_format
"#{::Time::DATE_FORMATS[:_sqlserver_datetime]}.%N".freeze
end

def fast_string_to_time_zone
::Time.zone || ActiveSupport::TimeZone.new('UTC')
end

end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,12 @@ def type
:datetimeoffset
end

def type_cast_for_schema(value)
serialize(value).inspect
end

def sqlserver_type
"datetimeoffset(#{precision.to_i})"
end

def quoted(value)
datetime = value.to_s(:_sqlserver_datetimeoffset)
Utils.quote_string_single(datetime)
end

private

def fast_string_to_time(string)
dateformat = ::Time::DATE_FORMATS[:_sqlserver_dateformat]
::Time.strptime string, "#{dateformat} %H:%M:%S.%N %:z"
end

def zone_conversion(value)
value
Utils.quote_string_single(value)
end

end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def sqlserver_type

private

def fast_string_to_time_format
::Time::DATE_FORMATS[:_sqlserver_datetime]
end

def apply_seconds_precision(value)
value.change usec: 0
end
Expand Down
16 changes: 10 additions & 6 deletions lib/active_record/connection_adapters/sqlserver/type/time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ class Time < ActiveRecord::Type::Time

def serialize(value)
return super unless value.acts_like?(:time)
Data.new super, self
time = value.to_s(:_sqlserver_time).tap do |v|
fraction = quote_fractional(value)
v << ".#{fraction}" unless fraction.to_i.zero?
end
Data.new time, self
end

def deserialize(value)
value.is_a?(Data) ? super(value.value) : super
end

def type_cast_for_schema(value)
Expand All @@ -20,11 +28,7 @@ def sqlserver_type
end

def quoted(value)
time = value.to_s(:_sqlserver_time).tap do |v|
fraction = quote_fractional(value)
v << ".#{fraction}" unless fraction.to_i.zero?
end
Utils.quote_string_single(time)
Utils.quote_string_single(value)
end

private
Expand Down
9 changes: 8 additions & 1 deletion test/cases/column_test_sqlserver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,14 @@ def assert_obj_set_and_save(attribute, value)
type.limit.must_be_nil
type.precision.must_be_nil
type.scale.must_be_nil
# Can cast strings.
# Can cast strings. SQL Server format.
obj.date = '04-01-0001'
obj.date.must_equal Date.civil(0001, 4, 1)
obj.save!
obj.date.must_equal Date.civil(0001, 4, 1)
obj.reload
obj.date.must_equal Date.civil(0001, 4, 1)
# Can cast strings. ISO format.
obj.date = '0001-04-01'
obj.date.must_equal Date.civil(0001, 4, 1)
obj.save!
Expand Down