Skip to content

Commit fd020b3

Browse files
committed
New ActiveRecord::Type objects for SQLServer.
1 parent 729db2d commit fd020b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1316
-611
lines changed

README.md

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,6 @@ This is a long story, but if you are not working with a legacy database and you
1818
http://wiki.github.com/rails-sqlserver/activerecord-sqlserver-adapter/rails-db-rake-tasks
1919

2020

21-
#### Date/Time Data Type Hinting
22-
23-
SQL Server 2005 does not include a native data type for just `date` or `time`, it only has `datetime`. To pass the ActiveRecord tests we implemented two simple class methods that can teach your models to coerce column information to be cast correctly. Simply pass a list of symbols to either the `coerce_sqlserver_date` or `coerce_sqlserver_time` methods that correspond to 'datetime' columns that need to be cast correctly.
24-
25-
```ruby
26-
class Topic < ActiveRecord::Base
27-
coerce_sqlserver_date :last_read
28-
coerce_sqlserver_time :bonus_time
29-
end
30-
```
31-
32-
This implementation has some limitations. To date we can only coerce date/time types for models that conform to the expected ActiveRecord class to table naming conventions. So a table of 'foo_bar_widgets' will look for coerced column types in the FooBarWidget class.
33-
34-
3521
#### Executing Stored Procedures
3622

3723
Every class that sub classes ActiveRecord::Base will now have an execute_procedure class method to use. This method takes the name of the stored procedure which can be a string or symbol and any number of variables to pass to the procedure. Arguments will automatically be quoted per the connection's standards as normal. For example:

lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,11 @@ module ConnectionAdapters
33
module SQLServer
44
module CoreExt
55
module ActiveRecord
6-
extend ActiveSupport::Concern
76

8-
included do
9-
class_attribute :coerced_sqlserver_date_columns, :coerced_sqlserver_time_columns
10-
self.coerced_sqlserver_date_columns = Set.new
11-
self.coerced_sqlserver_time_columns = Set.new
12-
end
7+
extend ActiveSupport::Concern
138

149
module ClassMethods
10+
1511
def execute_procedure(proc_name, *variables)
1612
if connection.respond_to?(:execute_procedure)
1713
connection.execute_procedure(proc_name, *variables)
@@ -20,14 +16,8 @@ def execute_procedure(proc_name, *variables)
2016
end
2117
end
2218

23-
def coerce_sqlserver_date(*attributes)
24-
self.coerced_sqlserver_date_columns += attributes.map(&:to_s)
25-
end
26-
27-
def coerce_sqlserver_time(*attributes)
28-
self.coerced_sqlserver_time_columns += attributes.map(&:to_s)
29-
end
3019
end
20+
3121
end
3222
end
3323
end

lib/active_record/connection_adapters/sqlserver/quoting.rb

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,10 @@ def unquoted_false
4444
0
4545
end
4646

47-
def quoted_datetime(value)
48-
if value.acts_like?(:time)
49-
time_zone_qualified_value = quoted_value_acts_like_time_filter(value)
50-
if value.is_a?(Date)
51-
time_zone_qualified_value.iso8601(3).to(18)
52-
else
53-
time_zone_qualified_value.iso8601(3).to(22)
54-
end
55-
else
56-
quoted_date(value)
57-
end
58-
end
59-
60-
def quoted_full_iso8601(value)
61-
if value.acts_like?(:time)
62-
value.is_a?(Date) ? quoted_value_acts_like_time_filter(value).to_time.xmlschema.to(18) : quoted_value_acts_like_time_filter(value).iso8601(7).to(22)
63-
else
64-
quoted_date(value)
65-
end
66-
end
67-
6847
def quoted_date(value)
6948
if value.acts_like?(:time) && value.respond_to?(:usec)
70-
"#{super}.#{sprintf('%03d', value.usec / 1000)}"
49+
precision = (BigDecimal(value.usec.to_s) / 1_000_000).round(3).to_s.split('.').last
50+
"#{super}.#{precision}"
7151
elsif value.acts_like?(:date)
7252
value.to_s(:_sqlserver_dateformat)
7353
else
@@ -78,16 +58,20 @@ def quoted_date(value)
7858

7959
private
8060

81-
def _quote(value) # , column = nil
61+
def _quote(value)
8262
case value
63+
when Type::Binary::Data
64+
"0x#{value.hex}"
65+
when SQLServer::Type::Quoter
66+
value.quote_ss_value
8367
when String, ActiveSupport::Multibyte::Chars
8468
if value.is_utf8?
8569
"#{QUOTED_STRING_PREFIX}#{super}"
8670
else
8771
super
8872
end
8973
else
90-
super(value)
74+
super
9175
end
9276
end
9377

lib/active_record/connection_adapters/sqlserver/schema_statements.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def indexes(table_name, name = nil)
4545
def columns(table_name, _name = nil)
4646
return [] if table_name.blank?
4747
column_definitions(table_name).map do |ci|
48-
sqlserver_options = ci.except(:name, :default_value, :type, :null).merge(database_year: database_year)
48+
sqlserver_options = ci.slice :ordinal_position, :is_primary, :is_identity, :default_function
4949
cast_type = lookup_cast_type(ci[:type])
5050
new_column ci[:name], ci[:default_value], cast_type, ci[:type], ci[:null], sqlserver_options
5151
end
@@ -199,6 +199,7 @@ def column_definitions(table_name)
199199
columns.COLUMN_DEFAULT AS default_value,
200200
columns.NUMERIC_SCALE AS numeric_scale,
201201
columns.NUMERIC_PRECISION AS numeric_precision,
202+
columns.DATETIME_PRECISION AS datetime_precision,
202203
columns.ordinal_position,
203204
CASE
204205
WHEN columns.DATA_TYPE IN ('nchar','nvarchar') THEN columns.CHARACTER_MAXIMUM_LENGTH
@@ -245,11 +246,13 @@ def column_definitions(table_name)
245246
ci[:type] = case ci[:type]
246247
when /^bit|image|text|ntext|datetime$/
247248
ci[:type]
249+
when /^time$/i
250+
"#{ci[:type]}(#{ci[:datetime_precision]})"
248251
when /^numeric|decimal$/i
249252
"#{ci[:type]}(#{ci[:numeric_precision]},#{ci[:numeric_scale]})"
250253
when /^float|real$/i
251254
"#{ci[:type]}(#{ci[:numeric_precision]})"
252-
when /^char|nchar|varchar|nvarchar|varbinary|bigint|int|smallint$/
255+
when /^char|nchar|varchar|nvarchar|binary|varbinary|bigint|int|smallint$/
253256
ci[:length].to_i == -1 ? "#{ci[:type]}(max)" : "#{ci[:type]}(#{ci[:length]})"
254257
else
255258
ci[:type]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
require 'active_record/type'
2+
require 'active_record/connection_adapters/sqlserver/type/core_ext/value.rb'
3+
require 'active_record/connection_adapters/sqlserver/type/castable.rb'
4+
require 'active_record/connection_adapters/sqlserver/type/quoter.rb'
5+
# Exact Numerics
6+
require 'active_record/connection_adapters/sqlserver/type/integer.rb'
7+
require 'active_record/connection_adapters/sqlserver/type/big_integer.rb'
8+
require 'active_record/connection_adapters/sqlserver/type/small_integer.rb'
9+
require 'active_record/connection_adapters/sqlserver/type/tiny_integer.rb'
10+
require 'active_record/connection_adapters/sqlserver/type/boolean.rb'
11+
require 'active_record/connection_adapters/sqlserver/type/decimal.rb'
12+
require 'active_record/connection_adapters/sqlserver/type/money.rb'
13+
require 'active_record/connection_adapters/sqlserver/type/small_money.rb'
14+
# Approximate Numerics
15+
require 'active_record/connection_adapters/sqlserver/type/float.rb'
16+
# Date and Time
17+
require 'active_record/connection_adapters/sqlserver/type/date.rb'
18+
require 'active_record/connection_adapters/sqlserver/type/datetime.rb'
19+
require 'active_record/connection_adapters/sqlserver/type/smalldatetime.rb'
20+
require 'active_record/connection_adapters/sqlserver/type/time.rb'
21+
# Character Strings
22+
require 'active_record/connection_adapters/sqlserver/type/string.rb'
23+
require 'active_record/connection_adapters/sqlserver/type/char.rb'
24+
require 'active_record/connection_adapters/sqlserver/type/varchar.rb'
25+
require 'active_record/connection_adapters/sqlserver/type/varchar_max.rb'
26+
require 'active_record/connection_adapters/sqlserver/type/text.rb'
27+
# Unicode Character Strings
28+
require 'active_record/connection_adapters/sqlserver/type/unicode_string.rb'
29+
require 'active_record/connection_adapters/sqlserver/type/unicode_char.rb'
30+
require 'active_record/connection_adapters/sqlserver/type/unicode_varchar.rb'
31+
require 'active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb'
32+
require 'active_record/connection_adapters/sqlserver/type/unicode_text.rb'
33+
# Binary Strings
34+
require 'active_record/connection_adapters/sqlserver/type/binary.rb'
35+
require 'active_record/connection_adapters/sqlserver/type/varbinary.rb'
36+
require 'active_record/connection_adapters/sqlserver/type/varbinary_max.rb'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module ActiveRecord
2+
module ConnectionAdapters
3+
module SQLServer
4+
module Type
5+
class BigInteger < Integer
6+
7+
8+
9+
end
10+
end
11+
end
12+
end
13+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module ActiveRecord
2+
module ConnectionAdapters
3+
module SQLServer
4+
module Type
5+
class Binary < ActiveRecord::Type::Binary
6+
7+
8+
end
9+
end
10+
end
11+
end
12+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module ActiveRecord
2+
module ConnectionAdapters
3+
module SQLServer
4+
module Type
5+
class Boolean < ActiveRecord::Type::Boolean
6+
7+
include Castable
8+
9+
end
10+
end
11+
end
12+
end
13+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module ActiveRecord
2+
module ConnectionAdapters
3+
module SQLServer
4+
module Type
5+
module Castable
6+
7+
def type_cast_from_database(value)
8+
type_cast_from_ss_database? ? super : value
9+
end
10+
11+
end
12+
end
13+
end
14+
end
15+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module ActiveRecord
2+
module ConnectionAdapters
3+
module SQLServer
4+
module Type
5+
class Char < String
6+
7+
8+
end
9+
end
10+
end
11+
end
12+
end

0 commit comments

Comments
 (0)