rails-sqlserver-2000-2005-adapter 2.2.19 → 2.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +29 -0
- data/README.rdoc +1 -2
- data/RUNNING_UNIT_TESTS +10 -6
- data/Rakefile +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +10 -8
- data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/active_record.rb +150 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/dbi.rb +96 -0
- data/test/cases/specific_schema_test_sqlserver.rb +17 -0
- data/test/schema/sqlserver_specific_schema.rb +1 -0
- metadata +4 -5
- data/lib/core_ext/active_record.rb +0 -151
- data/lib/core_ext/dbi.rb +0 -85
- data/lib/rails-sqlserver-2000-2005-adapter.rb +0 -1
data/CHANGELOG
CHANGED
@@ -1,6 +1,35 @@
|
|
1
1
|
|
2
2
|
MASTER
|
3
3
|
|
4
|
+
*
|
5
|
+
|
6
|
+
|
7
|
+
* 2.2.21 * (September 10th, 2009)
|
8
|
+
|
9
|
+
* Changes for gem best practices per http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices
|
10
|
+
Details of such are as follows: [Ken Collins]
|
11
|
+
- Removed rails-sqlserver-2000-2005-adapter.rb load file for old github usage.
|
12
|
+
- Move the core_ext directory to active_record/connection_adapters/sqlserver_adapter/core_ext
|
13
|
+
- Renamespace SQLServerDBI to ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::DBI
|
14
|
+
- Renamespace ActiveRecord::ConnectionAdapters::SQLServerActiveRecordExtensions to ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::ActiveRecord
|
15
|
+
|
16
|
+
|
17
|
+
* 2.2.20 * (September 10th, 2009)
|
18
|
+
|
19
|
+
* Implement a new remove_default_constraint method that uses sp_helpconstraint [Ken Collins]
|
20
|
+
|
21
|
+
* Use a lazy match in add_order_by_for_association_limiting! to allow sub selects to be used. Resolves
|
22
|
+
ticket #11.
|
23
|
+
|
24
|
+
* Add default rake task back for testing. Runs the namespaced sqlserver:test_sqlserver_odbc.
|
25
|
+
Resolves ticket #10 [Ken Collins]
|
26
|
+
|
27
|
+
* Default value detection in column_definitions is kinder to badly formatted, or long winded user
|
28
|
+
defined functions, for default values. Resolves ticket #8 [Ken Collins]
|
29
|
+
|
30
|
+
* Make sure bigint SQL Server data type can be used and converted back to Bignum as expected. [Ken Collins]
|
31
|
+
|
32
|
+
|
4
33
|
* 2.2.19 * (June 19th, 2009)
|
5
34
|
|
6
35
|
* Leave quoted column names as is. Resolves ticket #36 [Vince Puzzella]
|
data/README.rdoc
CHANGED
@@ -150,10 +150,9 @@ Here are some external links for libraries and/or tutorials on how to install an
|
|
150
150
|
|
151
151
|
== Contributing
|
152
152
|
|
153
|
-
If you’d like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Google list, IRC, or post a ticket
|
153
|
+
If you’d like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Google list, IRC, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the RUNNING_UNIT_TESTS file for the details of how to run the unit tests.
|
154
154
|
|
155
155
|
* Github: http://github.com/rails-sqlserver
|
156
|
-
* Lighthouse: http://rails-sqlserver.lighthouseapp.com/projects/20277-sql-server-05-adapter/tickets
|
157
156
|
* Google Group: http://groups.google.com/group/rails-sqlserver-adapter
|
158
157
|
* IRC Room: #rails-sqlserver on irc.freenode.net
|
159
158
|
|
data/RUNNING_UNIT_TESTS
CHANGED
@@ -5,12 +5,19 @@ The default names for the test databases are "activerecord_unittest" and
|
|
5
5
|
to update the connection adapter setups you want to test with in
|
6
6
|
test/connections/<your database>/connection.rb.
|
7
7
|
|
8
|
+
The connection files make certain assumptions. For instance, the ODBC connection
|
9
|
+
assumes you have a DSN setup that matches the name of the default database names.
|
10
|
+
|
8
11
|
|
9
12
|
== Requirements
|
10
13
|
|
11
14
|
The following gems need to be installed. Make sure you have gems.github.com as a
|
12
|
-
source. http://github.com/
|
15
|
+
source. Info here. http://gems.github.com/
|
16
|
+
|
17
|
+
We use echoe for packagemanagement to rubyforge. Not needed really for the tests
|
18
|
+
but since we need it... you need to install it.
|
13
19
|
|
20
|
+
* gem install echoe
|
14
21
|
* gem install thoughtbot-shoulda -s http://gems.github.com
|
15
22
|
* gem install mocha
|
16
23
|
|
@@ -21,11 +28,8 @@ is assumed to exist:
|
|
21
28
|
#{RAILS_ROOT}/vendor/plugins/adapters/sqlserver
|
22
29
|
#{RAILS_ROOT}/vendor/rails/activerecord/test
|
23
30
|
|
24
|
-
Define a user named 'rails' in SQL Server with all privileges granted
|
25
|
-
|
26
|
-
which allows you to set a default password for the current session.
|
27
|
-
|
28
|
-
Then run "rake create_databases".
|
31
|
+
Define a user named 'rails' in SQL Server with all privileges granted for the
|
32
|
+
test databases. Use an empty password for said user.
|
29
33
|
|
30
34
|
|
31
35
|
== Running with Rake
|
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rake'
|
|
3
3
|
require 'rake/testtask'
|
4
4
|
require 'echoe'
|
5
5
|
|
6
|
-
Echoe.new('activerecord-sqlserver-adapter','2.2.
|
6
|
+
Echoe.new('activerecord-sqlserver-adapter','2.2.21') do |p|
|
7
7
|
p.summary = "SQL Server 2000, 2005 and 2008 Adapter For Rails."
|
8
8
|
p.description = "SQL Server 2000, 2005 and 2008 Adapter For Rails."
|
9
9
|
p.author = ["Ken Collins","Murray Steele","Shawn Balestracci","Joe Rafaniello","Tom Ward"]
|
@@ -11,7 +11,7 @@ Echoe.new('activerecord-sqlserver-adapter','2.2.19') do |p|
|
|
11
11
|
p.url = "http://github.com/rails-sqlserver"
|
12
12
|
p.runtime_dependencies = ["dbi =0.4.1","dbd-odbc =0.2.4"]
|
13
13
|
p.include_gemspec = false
|
14
|
-
p.ignore_pattern = ["autotest/*","*.gemspec"
|
14
|
+
p.ignore_pattern = ["autotest/*","*.gemspec"]
|
15
15
|
p.project = 'arsqlserver'
|
16
16
|
end
|
17
17
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_adapter'
|
2
2
|
require_library_or_gem 'dbi' unless defined?(DBI)
|
3
|
-
require 'core_ext/dbi'
|
4
|
-
require 'core_ext/active_record'
|
3
|
+
require 'active_record/connection_adapters/sqlserver_adapter/core_ext/dbi'
|
4
|
+
require 'active_record/connection_adapters/sqlserver_adapter/core_ext/active_record'
|
5
5
|
require 'base64'
|
6
6
|
|
7
7
|
module ActiveRecord
|
@@ -183,7 +183,7 @@ module ActiveRecord
|
|
183
183
|
class SQLServerAdapter < AbstractAdapter
|
184
184
|
|
185
185
|
ADAPTER_NAME = 'SQLServer'.freeze
|
186
|
-
VERSION = '2.2.
|
186
|
+
VERSION = '2.2.21'.freeze
|
187
187
|
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
|
188
188
|
SUPPORTED_VERSIONS = [2000,2005,2008].freeze
|
189
189
|
LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].freeze
|
@@ -698,7 +698,7 @@ module ActiveRecord
|
|
698
698
|
# Disertation http://gist.github.com/24073
|
699
699
|
# Information http://weblogs.sqlteam.com/jeffs/archive/2007/12/13/select-distinct-order-by-error.aspx
|
700
700
|
return sql if options[:order].blank?
|
701
|
-
columns = sql.match(/SELECT\s+DISTINCT(
|
701
|
+
columns = sql.match(/SELECT\s+DISTINCT(.*?)FROM/)[1].strip
|
702
702
|
sql.sub!(/SELECT\s+DISTINCT/,'SELECT')
|
703
703
|
sql << "GROUP BY #{columns} ORDER BY #{order_to_min_set(options[:order])}"
|
704
704
|
end
|
@@ -908,9 +908,10 @@ module ActiveRecord
|
|
908
908
|
end
|
909
909
|
|
910
910
|
def remove_default_constraint(table_name, column_name)
|
911
|
-
|
912
|
-
|
913
|
-
|
911
|
+
select_all("EXEC sp_helpconstraint '#{quote_string(table_name)}','nomsg'").select do |row|
|
912
|
+
row['constraint_type'] == "DEFAULT on column #{column_name}"
|
913
|
+
end.each do |row|
|
914
|
+
do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{row['constraint_name']}"
|
914
915
|
end
|
915
916
|
end
|
916
917
|
|
@@ -1081,7 +1082,8 @@ module ActiveRecord
|
|
1081
1082
|
when nil, '(null)', '(NULL)'
|
1082
1083
|
nil
|
1083
1084
|
else
|
1084
|
-
ci[:default_value].match(/\A\(+N?'?(.*?)'?\)+\Z/)
|
1085
|
+
match_data = ci[:default_value].match(/\A\(+N?'?(.*?)'?\)+\Z/)
|
1086
|
+
match_data ? match_data[1] : nil
|
1085
1087
|
end
|
1086
1088
|
ci[:null] = ci[:is_nullable].to_i == 1 ; ci.delete(:is_nullable)
|
1087
1089
|
ci
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'active_record/version'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module SQLServerCoreExtensions
|
6
|
+
|
7
|
+
|
8
|
+
module ActiveRecord
|
9
|
+
|
10
|
+
def self.included(klass)
|
11
|
+
klass.extend ClassMethods
|
12
|
+
class << klass
|
13
|
+
alias_method_chain :reset_column_information, :sqlserver_cache_support
|
14
|
+
alias_method_chain :add_order!, :sqlserver_unique_checking
|
15
|
+
alias_method_chain :add_limit!, :sqlserver_order_checking
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
def execute_procedure(proc_name, *variables)
|
22
|
+
if connection.respond_to?(:execute_procedure)
|
23
|
+
connection.execute_procedure(proc_name,*variables)
|
24
|
+
else
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def coerce_sqlserver_date(*attributes)
|
30
|
+
write_inheritable_attribute :coerced_sqlserver_date_columns, Set.new(attributes.map(&:to_s))
|
31
|
+
end
|
32
|
+
|
33
|
+
def coerce_sqlserver_time(*attributes)
|
34
|
+
write_inheritable_attribute :coerced_sqlserver_time_columns, Set.new(attributes.map(&:to_s))
|
35
|
+
end
|
36
|
+
|
37
|
+
def coerced_sqlserver_date_columns
|
38
|
+
read_inheritable_attribute(:coerced_sqlserver_date_columns) || []
|
39
|
+
end
|
40
|
+
|
41
|
+
def coerced_sqlserver_time_columns
|
42
|
+
read_inheritable_attribute(:coerced_sqlserver_time_columns) || []
|
43
|
+
end
|
44
|
+
|
45
|
+
def reset_column_information_with_sqlserver_cache_support
|
46
|
+
connection.send(:initialize_sqlserver_caches) if connection.respond_to?(:sqlserver?)
|
47
|
+
reset_column_information_without_sqlserver_cache_support
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def add_limit_with_sqlserver_order_checking!(sql, options, scope = :auto)
|
53
|
+
if connection.respond_to?(:sqlserver?)
|
54
|
+
scope = scope(:find) if :auto == scope
|
55
|
+
if scope
|
56
|
+
options = options.dup
|
57
|
+
scoped_order = scope[:order]
|
58
|
+
order = options[:order]
|
59
|
+
if order && scoped_order
|
60
|
+
options[:order] = add_order_with_sqlserver_unique_checking!('', order, scope).gsub(/^ ORDER BY /,'')
|
61
|
+
elsif scoped_order
|
62
|
+
options[:order] = scoped_order
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
add_limit_without_sqlserver_order_checking!(sql, options, scope)
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_order_with_sqlserver_unique_checking!(sql, order, scope = :auto)
|
70
|
+
if connection.respond_to?(:sqlserver?)
|
71
|
+
order_sql = ''
|
72
|
+
add_order_without_sqlserver_unique_checking!(order_sql, order, scope)
|
73
|
+
unless order_sql.blank?
|
74
|
+
unique_order_hash = {}
|
75
|
+
select_table_name = connection.send(:get_table_name,sql)
|
76
|
+
select_table_name.tr!('[]','') if select_table_name
|
77
|
+
orders_and_dirs_set = connection.send(:orders_and_dirs_set,order_sql)
|
78
|
+
unique_order_sql = orders_and_dirs_set.inject([]) do |array,order_dir|
|
79
|
+
ord, dir = order_dir
|
80
|
+
ord_tn_and_cn = ord.to_s.split('.').map{|o|o.tr('[]','')}
|
81
|
+
ord_table_name, ord_column_name = if ord_tn_and_cn.size > 1
|
82
|
+
ord_tn_and_cn
|
83
|
+
else
|
84
|
+
[nil, ord_tn_and_cn.first]
|
85
|
+
end
|
86
|
+
if (ord_table_name && ord_table_name == select_table_name && unique_order_hash[ord_column_name]) || unique_order_hash[ord_column_name]
|
87
|
+
array
|
88
|
+
else
|
89
|
+
unique_order_hash[ord_column_name] = true
|
90
|
+
array << "#{ord} #{dir}".strip
|
91
|
+
end
|
92
|
+
end.join(', ')
|
93
|
+
sql << " ORDER BY #{unique_order_sql}"
|
94
|
+
end
|
95
|
+
else
|
96
|
+
add_order_without_sqlserver_unique_checking!(sql, order, scope)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
module JoinAssociationChanges
|
103
|
+
|
104
|
+
def self.included(klass)
|
105
|
+
klass.class_eval do
|
106
|
+
include InstanceMethods
|
107
|
+
alias_method_chain :aliased_table_name_for, :sqlserver_support
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module InstanceMethods
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
# An exact copy, except this method has a Regexp escape on the quoted table name.
|
116
|
+
def aliased_table_name_for_with_sqlserver_support(name,suffix=nil)
|
117
|
+
if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{Regexp.escape(active_record.connection.quote_table_name(name.downcase))}\son}i
|
118
|
+
@join_dependency.table_aliases[name] += 1
|
119
|
+
end
|
120
|
+
unless @join_dependency.table_aliases[name].zero?
|
121
|
+
# if the table name has been used, then use an alias
|
122
|
+
name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}"
|
123
|
+
table_index = @join_dependency.table_aliases[name]
|
124
|
+
@join_dependency.table_aliases[name] += 1
|
125
|
+
name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0
|
126
|
+
else
|
127
|
+
@join_dependency.table_aliases[name] += 1
|
128
|
+
end
|
129
|
+
name
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::ActiveRecord
|
145
|
+
|
146
|
+
if ActiveRecord::VERSION::MAJOR == 2 && ActiveRecord::VERSION::MINOR >= 3
|
147
|
+
require 'active_record/associations'
|
148
|
+
ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.send :include, ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::ActiveRecord::JoinAssociationChanges
|
149
|
+
end
|
150
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module SQLServerCoreExtensions
|
5
|
+
|
6
|
+
|
7
|
+
module DBI
|
8
|
+
|
9
|
+
module Timestamp
|
10
|
+
# Deprecated DBI. See documentation for Type::SqlserverTimestamp which
|
11
|
+
# this method tries to mimic as ODBC is still going to convert SQL Server
|
12
|
+
# milliconds to whole number representation of nanoseconds.
|
13
|
+
def to_sqlserver_string
|
14
|
+
datetime, nanoseconds = to_s.split('.')
|
15
|
+
"#{datetime}.#{sprintf("%03d",nanoseconds.to_i/1000000)}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Type
|
20
|
+
|
21
|
+
# Make sure we get DBI::Type::Timestamp returning a string NOT a time object
|
22
|
+
# that represents what is in the DB before type casting while letting core
|
23
|
+
# ActiveRecord do the reset. It is assumed that DBI is using ODBC connections
|
24
|
+
# and that ODBC::Timestamp is taking the native milliseconds that SQL Server
|
25
|
+
# stores and returning them incorrect using ODBC::Timestamp#fraction which is
|
26
|
+
# nanoseconds. Below shows the incorrect ODBC::Timestamp represented by DBI
|
27
|
+
# and the conversion we expect to have in the DB before type casting.
|
28
|
+
#
|
29
|
+
# "1985-04-15 00:00:00 0" # => "1985-04-15 00:00:00.000"
|
30
|
+
# "2008-11-08 10:24:36 30000000" # => "2008-11-08 10:24:36.003"
|
31
|
+
# "2008-11-08 10:24:36 123000000" # => "2008-11-08 10:24:36.123"
|
32
|
+
class SqlserverTimestamp
|
33
|
+
def self.parse(obj)
|
34
|
+
return nil if ::DBI::Type::Null.parse(obj).nil?
|
35
|
+
date, time, nanoseconds = obj.split(' ')
|
36
|
+
"#{date} #{time}.#{sprintf("%03d",nanoseconds.to_i/1000000)}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# The adapter and rails will parse our floats, decimals, and money field correctly
|
41
|
+
# from a string. Do not let the DBI::Type classes create Float/BigDecimal objects
|
42
|
+
# for us. Trust rails .type_cast to do what it is built to do.
|
43
|
+
class SqlserverForcedString
|
44
|
+
def self.parse(obj)
|
45
|
+
return nil if ::DBI::Type::Null.parse(obj).nil?
|
46
|
+
obj.to_s
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
module TypeUtil
|
53
|
+
|
54
|
+
def self.included(klass)
|
55
|
+
klass.extend ClassMethods
|
56
|
+
class << klass
|
57
|
+
alias_method_chain :type_name_to_module, :sqlserver_types
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module ClassMethods
|
62
|
+
|
63
|
+
# Capture all types classes that we need to handle directly for SQL Server
|
64
|
+
# and allow normal processing for those that we do not.
|
65
|
+
def type_name_to_module_with_sqlserver_types(type_name)
|
66
|
+
case type_name
|
67
|
+
when /^timestamp$/i
|
68
|
+
DBI::Type::SqlserverTimestamp
|
69
|
+
when /^float|decimal|money$/i
|
70
|
+
DBI::Type::SqlserverForcedString
|
71
|
+
else
|
72
|
+
type_name_to_module_without_sqlserver_types(type_name)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
if defined?(DBI::TypeUtil)
|
91
|
+
DBI::Type.send :include, ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::DBI::Type
|
92
|
+
DBI::TypeUtil.send :include, ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::DBI::TypeUtil
|
93
|
+
elsif defined?(DBI::Timestamp) # DEPRECATED in DBI 0.4.0 and above. Remove when 0.2.2 and lower is no longer supported.
|
94
|
+
DBI::Timestamp.send :include, ActiveRecord::ConnectionAdapters::SQLServerCoreExtensions::DBI::Timestamp
|
95
|
+
end
|
96
|
+
|
@@ -50,7 +50,24 @@ class SpecificSchemaTestSqlserver < ActiveRecord::TestCase
|
|
50
50
|
|
51
51
|
end
|
52
52
|
|
53
|
+
context 'with bigint column' do
|
53
54
|
|
55
|
+
setup do
|
56
|
+
@b5k = 5000
|
57
|
+
@bi5k = @edge_class.create! :bigint => @b5k, :description => 'Five Thousand'
|
58
|
+
@bnum = 9_000_000_000_000_000_000
|
59
|
+
@bimjr = @edge_class.create! :bigint => @bnum, :description => 'Close to max bignum'
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'can find by biginit' do
|
63
|
+
assert_equal @bi5k, @edge_class.find_by_bigint(@b5k)
|
64
|
+
assert_equal @b5k, @edge_class.find(:first, :select => 'bigint', :conditions => {:bigint => @b5k}).bigint
|
65
|
+
assert_equal @bimjr, @edge_class.find_by_bigint(@bnum)
|
66
|
+
assert_equal @bnum, @edge_class.find(:first, :select => 'bigint', :conditions => {:bigint => @bnum}).bigint
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
54
71
|
end
|
55
72
|
|
56
73
|
|
@@ -64,6 +64,7 @@ ActiveRecord::Schema.define do
|
|
64
64
|
|
65
65
|
create_table :sql_server_edge_schemas, :force => true do |t|
|
66
66
|
t.string :description
|
67
|
+
t.column :bigint, :bigint
|
67
68
|
end
|
68
69
|
|
69
70
|
execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'customers_view') DROP VIEW customers_view"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-sqlserver-2000-2005-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2009-
|
16
|
+
date: 2009-09-10 00:00:00 -07:00
|
17
17
|
default_executable:
|
18
18
|
dependencies: []
|
19
19
|
|
@@ -35,10 +35,9 @@ files:
|
|
35
35
|
- autotest/discover.rb
|
36
36
|
- autotest/railssqlserver.rb
|
37
37
|
- autotest/sqlserver.rb
|
38
|
-
- lib/rails-sqlserver-2000-2005-adapter.rb
|
39
38
|
- lib/active_record/connection_adapters/sqlserver_adapter.rb
|
40
|
-
- lib/core_ext/active_record.rb
|
41
|
-
- lib/core_ext/dbi.rb
|
39
|
+
- lib/active_record/connection_adapters/sqlserver_adapter/core_ext/active_record.rb
|
40
|
+
- lib/active_record/connection_adapters/sqlserver_adapter/core_ext/dbi.rb
|
42
41
|
has_rdoc: true
|
43
42
|
homepage: http://github.com/rails-sqlserver
|
44
43
|
post_install_message:
|
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'active_record/version'
|
2
|
-
|
3
|
-
module ActiveRecord
|
4
|
-
module ConnectionAdapters
|
5
|
-
module SQLServerActiveRecordExtensions
|
6
|
-
|
7
|
-
def self.included(klass)
|
8
|
-
klass.extend ClassMethods
|
9
|
-
class << klass
|
10
|
-
alias_method_chain :reset_column_information, :sqlserver_cache_support
|
11
|
-
alias_method_chain :add_order!, :sqlserver_unique_checking
|
12
|
-
alias_method_chain :add_limit!, :sqlserver_order_checking
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module ClassMethods
|
17
|
-
|
18
|
-
def execute_procedure(proc_name, *variables)
|
19
|
-
if connection.respond_to?(:execute_procedure)
|
20
|
-
connection.execute_procedure(proc_name,*variables)
|
21
|
-
else
|
22
|
-
[]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def coerce_sqlserver_date(*attributes)
|
27
|
-
write_inheritable_attribute :coerced_sqlserver_date_columns, Set.new(attributes.map(&:to_s))
|
28
|
-
end
|
29
|
-
|
30
|
-
def coerce_sqlserver_time(*attributes)
|
31
|
-
write_inheritable_attribute :coerced_sqlserver_time_columns, Set.new(attributes.map(&:to_s))
|
32
|
-
end
|
33
|
-
|
34
|
-
def coerced_sqlserver_date_columns
|
35
|
-
read_inheritable_attribute(:coerced_sqlserver_date_columns) || []
|
36
|
-
end
|
37
|
-
|
38
|
-
def coerced_sqlserver_time_columns
|
39
|
-
read_inheritable_attribute(:coerced_sqlserver_time_columns) || []
|
40
|
-
end
|
41
|
-
|
42
|
-
def reset_column_information_with_sqlserver_cache_support
|
43
|
-
connection.send(:initialize_sqlserver_caches) if connection.respond_to?(:sqlserver?)
|
44
|
-
reset_column_information_without_sqlserver_cache_support
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def add_limit_with_sqlserver_order_checking!(sql, options, scope = :auto)
|
50
|
-
if connection.respond_to?(:sqlserver?)
|
51
|
-
scope = scope(:find) if :auto == scope
|
52
|
-
if scope
|
53
|
-
options = options.dup
|
54
|
-
scoped_order = scope[:order]
|
55
|
-
order = options[:order]
|
56
|
-
if order && scoped_order
|
57
|
-
options[:order] = add_order_with_sqlserver_unique_checking!('', order, scope).gsub(/^ ORDER BY /,'')
|
58
|
-
elsif scoped_order
|
59
|
-
options[:order] = scoped_order
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
add_limit_without_sqlserver_order_checking!(sql, options, scope)
|
64
|
-
end
|
65
|
-
|
66
|
-
def add_order_with_sqlserver_unique_checking!(sql, order, scope = :auto)
|
67
|
-
if connection.respond_to?(:sqlserver?)
|
68
|
-
order_sql = ''
|
69
|
-
add_order_without_sqlserver_unique_checking!(order_sql, order, scope)
|
70
|
-
unless order_sql.blank?
|
71
|
-
unique_order_hash = {}
|
72
|
-
select_table_name = connection.send(:get_table_name,sql)
|
73
|
-
select_table_name.tr!('[]','') if select_table_name
|
74
|
-
orders_and_dirs_set = connection.send(:orders_and_dirs_set,order_sql)
|
75
|
-
unique_order_sql = orders_and_dirs_set.inject([]) do |array,order_dir|
|
76
|
-
ord, dir = order_dir
|
77
|
-
ord_tn_and_cn = ord.to_s.split('.').map{|o|o.tr('[]','')}
|
78
|
-
ord_table_name, ord_column_name = if ord_tn_and_cn.size > 1
|
79
|
-
ord_tn_and_cn
|
80
|
-
else
|
81
|
-
[nil, ord_tn_and_cn.first]
|
82
|
-
end
|
83
|
-
if (ord_table_name && ord_table_name == select_table_name && unique_order_hash[ord_column_name]) || unique_order_hash[ord_column_name]
|
84
|
-
array
|
85
|
-
else
|
86
|
-
unique_order_hash[ord_column_name] = true
|
87
|
-
array << "#{ord} #{dir}".strip
|
88
|
-
end
|
89
|
-
end.join(', ')
|
90
|
-
sql << " ORDER BY #{unique_order_sql}"
|
91
|
-
end
|
92
|
-
else
|
93
|
-
add_order_without_sqlserver_unique_checking!(sql, order, scope)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::SQLServerActiveRecordExtensions
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
if ActiveRecord::VERSION::MAJOR == 2 && ActiveRecord::VERSION::MINOR >= 3
|
109
|
-
|
110
|
-
require 'active_record/associations'
|
111
|
-
module ActiveRecord
|
112
|
-
module ConnectionAdapters
|
113
|
-
module SQLServerJoinAssociationChanges
|
114
|
-
|
115
|
-
def self.included(klass)
|
116
|
-
klass.class_eval do
|
117
|
-
include InstanceMethods
|
118
|
-
alias_method_chain :aliased_table_name_for, :sqlserver_support
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
module InstanceMethods
|
123
|
-
|
124
|
-
protected
|
125
|
-
|
126
|
-
# An exact copy, except this method has a Regexp escape on the quoted table name.
|
127
|
-
def aliased_table_name_for_with_sqlserver_support(name,suffix=nil)
|
128
|
-
if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{Regexp.escape(active_record.connection.quote_table_name(name.downcase))}\son}i
|
129
|
-
@join_dependency.table_aliases[name] += 1
|
130
|
-
end
|
131
|
-
unless @join_dependency.table_aliases[name].zero?
|
132
|
-
# if the table name has been used, then use an alias
|
133
|
-
name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}"
|
134
|
-
table_index = @join_dependency.table_aliases[name]
|
135
|
-
@join_dependency.table_aliases[name] += 1
|
136
|
-
name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0
|
137
|
-
else
|
138
|
-
@join_dependency.table_aliases[name] += 1
|
139
|
-
end
|
140
|
-
name
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.send :include, ActiveRecord::ConnectionAdapters::SQLServerJoinAssociationChanges
|
149
|
-
|
150
|
-
end
|
151
|
-
|
data/lib/core_ext/dbi.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
|
2
|
-
module SQLServerDBI
|
3
|
-
|
4
|
-
module Timestamp
|
5
|
-
# Deprecated DBI. See documentation for Type::SqlserverTimestamp which
|
6
|
-
# this method tries to mimic as ODBC is still going to convert SQL Server
|
7
|
-
# milliconds to whole number representation of nanoseconds.
|
8
|
-
def to_sqlserver_string
|
9
|
-
datetime, nanoseconds = to_s.split('.')
|
10
|
-
"#{datetime}.#{sprintf("%03d",nanoseconds.to_i/1000000)}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module Type
|
15
|
-
|
16
|
-
# Make sure we get DBI::Type::Timestamp returning a string NOT a time object
|
17
|
-
# that represents what is in the DB before type casting while letting core
|
18
|
-
# ActiveRecord do the reset. It is assumed that DBI is using ODBC connections
|
19
|
-
# and that ODBC::Timestamp is taking the native milliseconds that SQL Server
|
20
|
-
# stores and returning them incorrect using ODBC::Timestamp#fraction which is
|
21
|
-
# nanoseconds. Below shows the incorrect ODBC::Timestamp represented by DBI
|
22
|
-
# and the conversion we expect to have in the DB before type casting.
|
23
|
-
#
|
24
|
-
# "1985-04-15 00:00:00 0" # => "1985-04-15 00:00:00.000"
|
25
|
-
# "2008-11-08 10:24:36 30000000" # => "2008-11-08 10:24:36.003"
|
26
|
-
# "2008-11-08 10:24:36 123000000" # => "2008-11-08 10:24:36.123"
|
27
|
-
class SqlserverTimestamp
|
28
|
-
def self.parse(obj)
|
29
|
-
return nil if ::DBI::Type::Null.parse(obj).nil?
|
30
|
-
date, time, nanoseconds = obj.split(' ')
|
31
|
-
"#{date} #{time}.#{sprintf("%03d",nanoseconds.to_i/1000000)}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# The adapter and rails will parse our floats, decimals, and money field correctly
|
36
|
-
# from a string. Do not let the DBI::Type classes create Float/BigDecimal objects
|
37
|
-
# for us. Trust rails .type_cast to do what it is built to do.
|
38
|
-
class SqlserverForcedString
|
39
|
-
def self.parse(obj)
|
40
|
-
return nil if ::DBI::Type::Null.parse(obj).nil?
|
41
|
-
obj.to_s
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
module TypeUtil
|
48
|
-
|
49
|
-
def self.included(klass)
|
50
|
-
klass.extend ClassMethods
|
51
|
-
class << klass
|
52
|
-
alias_method_chain :type_name_to_module, :sqlserver_types
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
module ClassMethods
|
57
|
-
|
58
|
-
# Capture all types classes that we need to handle directly for SQL Server
|
59
|
-
# and allow normal processing for those that we do not.
|
60
|
-
def type_name_to_module_with_sqlserver_types(type_name)
|
61
|
-
case type_name
|
62
|
-
when /^timestamp$/i
|
63
|
-
DBI::Type::SqlserverTimestamp
|
64
|
-
when /^float|decimal|money$/i
|
65
|
-
DBI::Type::SqlserverForcedString
|
66
|
-
else
|
67
|
-
type_name_to_module_without_sqlserver_types(type_name)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
if defined?(DBI::TypeUtil)
|
80
|
-
DBI::Type.send :include, SQLServerDBI::Type
|
81
|
-
DBI::TypeUtil.send :include, SQLServerDBI::TypeUtil
|
82
|
-
elsif defined?(DBI::Timestamp) # DEPRECATED in DBI 0.4.0 and above. Remove when 0.2.2 and lower is no longer supported.
|
83
|
-
DBI::Timestamp.send :include, SQLServerDBI::Timestamp
|
84
|
-
end
|
85
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'active_record/connection_adapters/sqlserver_adapter'
|