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 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]
@@ -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 in Lighthouse. 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.
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
 
@@ -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/blog/97-github-loves-rubygems-1-2
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. Use an empty
25
- password for user 'rails', or alternatively use the OSQLPASSWORD environment variable
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.19') do |p|
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","lib/rails-sqlserver-2000-2005-adapter.rb"]
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.19'.freeze
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(.*)FROM/)[1].strip
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
- constraints = select_values("SELECT def.name FROM sysobjects def, syscolumns col, sysobjects tab WHERE col.cdefault = def.id AND col.name = '#{quote_string(column_name)}' AND tab.name = '#{quote_string(table_name)}' AND col.id = tab.id")
912
- constraints.each do |constraint|
913
- do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(constraint)}"
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/)[1]
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.19
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-06-18 00:00:00 -07:00
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
-
@@ -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'