rainux-2000-2005-adapter 2.2.15

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.
Files changed (38) hide show
  1. data/CHANGELOG +142 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +157 -0
  4. data/RUNNING_UNIT_TESTS +60 -0
  5. data/Rakefile +52 -0
  6. data/autotest/discover.rb +4 -0
  7. data/autotest/railssqlserver.rb +16 -0
  8. data/autotest/sqlserver.rb +54 -0
  9. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1017 -0
  10. data/lib/core_ext/active_record.rb +150 -0
  11. data/lib/core_ext/dbi.rb +85 -0
  12. data/lib/rails-sqlserver-2000-2005-adapter.rb +1 -0
  13. data/test/cases/aaaa_create_tables_test_sqlserver.rb +19 -0
  14. data/test/cases/adapter_test_sqlserver.rb +627 -0
  15. data/test/cases/attribute_methods_test_sqlserver.rb +33 -0
  16. data/test/cases/basics_test_sqlserver.rb +21 -0
  17. data/test/cases/calculations_test_sqlserver.rb +20 -0
  18. data/test/cases/column_test_sqlserver.rb +264 -0
  19. data/test/cases/connection_test_sqlserver.rb +103 -0
  20. data/test/cases/eager_association_test_sqlserver.rb +42 -0
  21. data/test/cases/execute_procedure_test_sqlserver.rb +33 -0
  22. data/test/cases/inheritance_test_sqlserver.rb +28 -0
  23. data/test/cases/method_scoping_test_sqlserver.rb +28 -0
  24. data/test/cases/migration_test_sqlserver.rb +93 -0
  25. data/test/cases/offset_and_limit_test_sqlserver.rb +89 -0
  26. data/test/cases/pessimistic_locking_test_sqlserver.rb +125 -0
  27. data/test/cases/query_cache_test_sqlserver.rb +24 -0
  28. data/test/cases/schema_dumper_test_sqlserver.rb +61 -0
  29. data/test/cases/specific_schema_test_sqlserver.rb +26 -0
  30. data/test/cases/sqlserver_helper.rb +119 -0
  31. data/test/cases/table_name_test_sqlserver.rb +22 -0
  32. data/test/cases/transaction_test_sqlserver.rb +93 -0
  33. data/test/cases/unicode_test_sqlserver.rb +44 -0
  34. data/test/connections/native_sqlserver/connection.rb +23 -0
  35. data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
  36. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  37. data/test/schema/sqlserver_specific_schema.rb +88 -0
  38. metadata +96 -0
@@ -0,0 +1,26 @@
1
+ require 'cases/sqlserver_helper'
2
+
3
+ class StringDefault < ActiveRecord::Base; end;
4
+
5
+ class SpecificSchemaTestSqlserver < ActiveRecord::TestCase
6
+
7
+ should 'default strings before save' do
8
+ default = StringDefault.new
9
+ assert_equal nil, default.string_with_null_default
10
+ assert_equal 'null', default.string_with_pretend_null_one
11
+ assert_equal '(null)', default.string_with_pretend_null_two
12
+ assert_equal 'NULL', default.string_with_pretend_null_three
13
+ assert_equal '(NULL)', default.string_with_pretend_null_four
14
+ assert_equal '(3)', default.string_with_pretend_paren_three
15
+ end
16
+
17
+ should 'default strings after save' do
18
+ default = StringDefault.create
19
+ assert_equal nil, default.string_with_null_default
20
+ assert_equal 'null', default.string_with_pretend_null_one
21
+ assert_equal '(null)', default.string_with_pretend_null_two
22
+ assert_equal 'NULL', default.string_with_pretend_null_three
23
+ assert_equal '(NULL)', default.string_with_pretend_null_four
24
+ end
25
+
26
+ end
@@ -0,0 +1,119 @@
1
+ require 'rubygems'
2
+ require 'shoulda'
3
+ require 'mocha'
4
+ require 'cases/helper'
5
+ require 'models/topic'
6
+ require 'active_record/version'
7
+
8
+ SQLSERVER_TEST_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'..'))
9
+ SQLSERVER_ASSETS_ROOT = SQLSERVER_TEST_ROOT + "/assets"
10
+ SQLSERVER_FIXTURES_ROOT = SQLSERVER_TEST_ROOT + "/fixtures"
11
+ SQLSERVER_MIGRATIONS_ROOT = SQLSERVER_TEST_ROOT + "/migrations"
12
+ SQLSERVER_SCHEMA_ROOT = SQLSERVER_TEST_ROOT + "/schema"
13
+ ACTIVERECORD_TEST_ROOT = File.expand_path(SQLSERVER_TEST_ROOT + "/../../../../rails/activerecord/test/")
14
+
15
+ ActiveRecord::Migration.verbose = false
16
+
17
+ # Defining our classes in one place as well as soem core tests that need coercing date/time types.
18
+
19
+ class TableWithRealColumn < ActiveRecord::Base; end
20
+ class FkTestHasFk < ActiveRecord::Base ; end
21
+ class FkTestHasPk < ActiveRecord::Base ; end
22
+ class NumericData < ActiveRecord::Base ; self.table_name = 'numeric_data' ; end
23
+ class CustomersView < ActiveRecord::Base ; self.table_name = 'customers_view' ; end
24
+ class StringDefaultsView < ActiveRecord::Base ; self.table_name = 'string_defaults_view' ; end
25
+ class StringDefaultsBigView < ActiveRecord::Base ; self.table_name = 'string_defaults_big_view' ; end
26
+ class SqlServerUnicode < ActiveRecord::Base ; end
27
+ class SqlServerString < ActiveRecord::Base ; end
28
+ class SqlServerChronic < ActiveRecord::Base
29
+ coerce_sqlserver_date :date
30
+ coerce_sqlserver_time :time
31
+ default_timezone = :utc
32
+ end
33
+ class Topic < ActiveRecord::Base
34
+ coerce_sqlserver_date :last_read
35
+ coerce_sqlserver_time :bonus_time
36
+ end
37
+ class Person < ActiveRecord::Base
38
+ coerce_sqlserver_date :favorite_day
39
+ end
40
+
41
+ # A module that we can include in classes where we want to override an active record test.
42
+
43
+ module SqlserverCoercedTest
44
+ def self.included(base)
45
+ base.extend ClassMethods
46
+ end
47
+ module ClassMethods
48
+ def coerced_tests
49
+ self.const_get(:COERCED_TESTS) rescue nil
50
+ end
51
+ def method_added(method)
52
+ if coerced_tests && coerced_tests.include?(method)
53
+ undef_method(method)
54
+ STDOUT.puts("Undefined coerced test: #{self.name}##{method}")
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ # Set weather to test unicode string defaults or not. Used from rake task.
61
+
62
+ if ENV['ENABLE_DEFAULT_UNICODE_TYPES'] == 'true'
63
+ puts "With enabled unicode string types"
64
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types = true
65
+ end
66
+
67
+ # Change the text database type to support ActiveRecord's tests for = on text columns which
68
+ # is not supported in SQL Server text columns, so use varchar(8000) instead.
69
+
70
+ if ActiveRecord::Base.connection.sqlserver_2000?
71
+ if ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types
72
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter.native_text_database_type = 'nvarchar(4000)'
73
+ else
74
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter.native_text_database_type = 'varchar(8000)'
75
+ end
76
+ end
77
+
78
+ # Our changes/additions to ActiveRecord test helpers specific for SQL Server.
79
+
80
+ ActiveRecord::Base.connection.class.class_eval do
81
+ IGNORED_SQL << %r|SELECT SCOPE_IDENTITY| << %r{INFORMATION_SCHEMA\.(TABLES|VIEWS|COLUMNS)}
82
+ IGNORED_SQL << %r|SELECT @@IDENTITY| << %r|SELECT @@ROWCOUNT| << %r|SELECT @@version| << %r|SELECT @@TRANCOUNT|
83
+ end
84
+
85
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter.class_eval do
86
+ def raw_select_with_query_record(sql, name = nil)
87
+ $queries_executed ||= []
88
+ $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
89
+ raw_select_without_query_record(sql,name)
90
+ end
91
+ alias_method_chain :raw_select, :query_record
92
+ end
93
+
94
+ module ActiveRecord
95
+ class TestCase < ActiveSupport::TestCase
96
+ class << self
97
+ def sqlserver_2000? ; ActiveRecord::Base.connection.sqlserver_2000? ; end
98
+ def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
99
+ def active_record_2_point_2? ; ActiveRecord::VERSION::MAJOR == 2 && ActiveRecord::VERSION::MINOR == 2 ; end
100
+ def active_record_2_point_3? ; ActiveRecord::VERSION::MAJOR == 2 && ActiveRecord::VERSION::MINOR == 3 ; end
101
+ end
102
+ def assert_sql(*patterns_to_match)
103
+ $queries_executed = []
104
+ yield
105
+ ensure
106
+ failed_patterns = []
107
+ patterns_to_match.each do |pattern|
108
+ failed_patterns << pattern unless $queries_executed.any?{ |sql| pattern === sql }
109
+ end
110
+ assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found in:\n#{$queries_executed.inspect}"
111
+ end
112
+ def sqlserver_2000? ; self.class.sqlserver_2000? ; end
113
+ def sqlserver_2005? ; self.class.sqlserver_2005? ; end
114
+ def active_record_2_point_2? ; self.class.active_record_2_point_2? ; end
115
+ def active_record_2_point_3? ; self.class.active_record_2_point_3? ; end
116
+ end
117
+ end
118
+
119
+
@@ -0,0 +1,22 @@
1
+ require 'cases/sqlserver_helper'
2
+ require 'models/order'
3
+
4
+ class TableNameTestSqlserver < ActiveRecord::TestCase
5
+
6
+ self.use_transactional_fixtures = false
7
+
8
+ def setup
9
+ Order.table_name = '[orders]'
10
+ Order.reset_column_information
11
+ end
12
+
13
+ should 'load columns with escaped table name for model' do
14
+ assert_equal 4, Order.columns.length
15
+ end
16
+
17
+ should 'not re-escape table name if it is escaped already for SQL queries' do
18
+ assert_sql(/SELECT \* FROM \[orders\]/) { Order.all }
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,93 @@
1
+ require 'cases/sqlserver_helper'
2
+ require 'models/ship'
3
+ require 'models/developer'
4
+
5
+ class TransactionTestSqlserver < ActiveRecord::TestCase
6
+
7
+ self.use_transactional_fixtures = false
8
+
9
+ setup :delete_ships
10
+
11
+ context 'Testing transaction basics' do
12
+
13
+ should 'allow ActiveRecord::Rollback to work in 1 transaction block' do
14
+ Ship.transaction do
15
+ Ship.create! :name => 'Black Pearl'
16
+ raise ActiveRecord::Rollback
17
+ end
18
+ assert_no_ships
19
+ end
20
+
21
+ should 'allow nested transactions to totally rollback' do
22
+ begin
23
+ Ship.transaction do
24
+ Ship.create! :name => 'Black Pearl'
25
+ Ship.transaction do
26
+ Ship.create! :name => 'Flying Dutchman'
27
+ raise 'HELL'
28
+ end
29
+ end
30
+ rescue Exception => e
31
+ assert_no_ships
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ context 'Testing #outside_transaction?' do
38
+
39
+ should 'work in simple usage' do
40
+ assert Ship.connection.outside_transaction?
41
+ Ship.connection.begin_db_transaction
42
+ assert !Ship.connection.outside_transaction?
43
+ Ship.connection.rollback_db_transaction
44
+ assert Ship.connection.outside_transaction?
45
+ end
46
+
47
+ should 'work inside nested transactions' do
48
+ assert Ship.connection.outside_transaction?
49
+ Ship.transaction do
50
+ assert !Ship.connection.outside_transaction?
51
+ Ship.transaction do
52
+ assert !Ship.connection.outside_transaction?
53
+ end
54
+ end
55
+ assert Ship.connection.outside_transaction?
56
+ end
57
+
58
+ should 'not call rollback if no transaction is active' do
59
+ assert_raise RuntimeError do
60
+ Ship.transaction do
61
+ Ship.connection.rollback_db_transaction
62
+ Ship.connection.expects(:rollback_db_transaction).never
63
+ raise "Rails doesn't scale!"
64
+ end
65
+ end
66
+ end
67
+
68
+ should 'test_open_transactions_count_is_reset_to_zero_if_no_transaction_active' do
69
+ Ship.transaction do
70
+ Ship.transaction do
71
+ Ship.connection.rollback_db_transaction
72
+ end
73
+ assert_equal 0, Ship.connection.open_transactions
74
+ end
75
+ assert_equal 0, Ship.connection.open_transactions
76
+ end
77
+
78
+ end unless active_record_2_point_2?
79
+
80
+
81
+
82
+ protected
83
+
84
+ def delete_ships
85
+ Ship.delete_all
86
+ end
87
+
88
+ def assert_no_ships
89
+ assert Ship.count.zero?, "Expected Ship to have no models but it did have:\n#{Ship.all.inspect}"
90
+ end
91
+
92
+ end
93
+
@@ -0,0 +1,44 @@
1
+ require 'cases/sqlserver_helper'
2
+
3
+ class UnicodeTestSqlserver < ActiveRecord::TestCase
4
+
5
+
6
+ context 'Testing basic saves and unicode limits' do
7
+
8
+ should 'save and reload simple nchar string' do
9
+ assert nchar_data = SqlServerUnicode.create!(:nchar => 'A')
10
+ assert_equal 'A', SqlServerUnicode.find(nchar_data.id).nchar
11
+ end
12
+
13
+ should 'save and reload simple nvarchar(max) string' do
14
+ test_string = 'Ken Collins'
15
+ assert nvarcharmax_data = SqlServerUnicode.create!(:nvarchar_max => test_string)
16
+ assert_equal test_string, SqlServerUnicode.find(nvarcharmax_data.id).nvarchar_max
17
+ end if sqlserver_2005?
18
+
19
+ should 'enforce default nchar_10 limit of 10' do
20
+ assert_raise(ActiveRecord::StatementInvalid) { SqlServerUnicode.create!(:nchar => '01234567891') }
21
+ end
22
+
23
+ should 'enforce default nvarchar_100 limit of 100' do
24
+ assert_raise(ActiveRecord::StatementInvalid) { SqlServerUnicode.create!(:nvarchar_100 => '0123456789'*10+'1') }
25
+ end
26
+
27
+ end
28
+
29
+ context 'Testing unicode data' do
30
+
31
+ setup do
32
+ @unicode_data = "一二34五六"
33
+ end
34
+
35
+ should 'insert into nvarchar field' do
36
+ assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
37
+ assert_equal @unicode_data, data.reload.nvarchar
38
+ end
39
+
40
+ end
41
+
42
+
43
+
44
+ end
@@ -0,0 +1,23 @@
1
+ print "Using native SQLServer\n"
2
+ require_dependency 'models/course'
3
+ require 'logger'
4
+
5
+ ActiveRecord::Base.logger = Logger.new("debug.log")
6
+
7
+ ActiveRecord::Base.configurations = {
8
+ 'arunit' => {
9
+ :adapter => 'sqlserver',
10
+ :host => 'localhost',
11
+ :username => 'rails',
12
+ :database => 'activerecord_unittest'
13
+ },
14
+ 'arunit2' => {
15
+ :adapter => 'sqlserver',
16
+ :host => 'localhost',
17
+ :username => 'rails',
18
+ :database => 'activerecord_unittest2'
19
+ }
20
+ }
21
+
22
+ ActiveRecord::Base.establish_connection 'arunit'
23
+ Course.establish_connection 'arunit2'
@@ -0,0 +1,25 @@
1
+ print "Using native SQLServer via ODBC\n"
2
+ require_dependency 'models/course'
3
+ require 'logger'
4
+
5
+ ActiveRecord::Base.logger = Logger.new("debug.log")
6
+
7
+ ActiveRecord::Base.configurations = {
8
+ 'arunit' => {
9
+ :adapter => 'sqlserver',
10
+ :mode => 'ODBC',
11
+ :host => 'localhost',
12
+ :username => 'rails',
13
+ :dsn => 'activerecord_unittest'
14
+ },
15
+ 'arunit2' => {
16
+ :adapter => 'sqlserver',
17
+ :mode => 'ODBC',
18
+ :host => 'localhost',
19
+ :username => 'rails',
20
+ :dsn => 'activerecord_unittest2'
21
+ }
22
+ }
23
+
24
+ ActiveRecord::Base.establish_connection 'arunit'
25
+ Course.establish_connection 'arunit2'
@@ -0,0 +1,11 @@
1
+ class TableWillNeverBeCreated < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table(:sqlserver_trans_table1) { }
5
+ create_table(:sqlserver_trans_table2) { raise ActiveRecord::StatementInvalid }
6
+ end
7
+
8
+ def self.down
9
+ end
10
+
11
+ end
@@ -0,0 +1,88 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ create_table :table_with_real_columns, :force => true do |t|
4
+ t.column :real_number, :real
5
+ # t.column :varchar_max, :varchar_max if ActiveRecord::Base.connection.sqlserver_2005?
6
+ end
7
+
8
+ create_table :defaults, :force => true do |t|
9
+ t.column :positive_integer, :integer, :default => 1
10
+ t.column :negative_integer, :integer, :default => -1
11
+ t.column :decimal_number, :decimal, :precision => 3, :scale => 2, :default => 2.78
12
+ end
13
+
14
+ create_table :string_defaults, :force => true do |t|
15
+ t.column :string_with_null_default, :string, :default => nil
16
+ t.column :string_with_pretend_null_one, :string, :default => 'null'
17
+ t.column :string_with_pretend_null_two, :string, :default => '(null)'
18
+ t.column :string_with_pretend_null_three, :string, :default => 'NULL'
19
+ t.column :string_with_pretend_null_four, :string, :default => '(NULL)'
20
+ t.column :string_with_pretend_paren_three, :string, :default => '(3)'
21
+ end
22
+
23
+ create_table :sql_server_chronics, :force => true do |t|
24
+ t.column :date, :date
25
+ t.column :time, :time
26
+ t.column :datetime, :datetime
27
+ t.column :timestamp, :timestamp
28
+ t.column :smalldatetime, :smalldatetime
29
+ end
30
+
31
+ create_table(:fk_test_has_fks, :force => true) { |t| t.column(:fk_id, :integer, :null => false) }
32
+ create_table(:fk_test_has_pks, :force => true) { }
33
+ execute <<-ADDFKSQL
34
+ ALTER TABLE fk_test_has_fks
35
+ ADD CONSTRAINT FK__fk_test_has_fk_fk_id
36
+ FOREIGN KEY (#{quote_column_name('fk_id')})
37
+ REFERENCES #{quote_table_name('fk_test_has_pks')} (#{quote_column_name('id')})
38
+ ADDFKSQL
39
+
40
+ create_table :sql_server_unicodes, :force => true do |t|
41
+ t.column :nchar, :nchar
42
+ t.column :nvarchar, :nvarchar
43
+ t.column :ntext, :ntext
44
+ t.column :ntext_10, :ntext, :limit => 10
45
+ t.column :nchar_10, :nchar, :limit => 10
46
+ t.column :nvarchar_100, :nvarchar, :limit => 100
47
+ if ActiveRecord::Base.connection.sqlserver_2005?
48
+ t.column :nvarchar_max, :nvarchar_max
49
+ t.column :nvarchar_max_10, :nvarchar_max, :limit => 10
50
+ end
51
+ end
52
+
53
+ create_table :sql_server_strings, :force => true do |t|
54
+ t.column :char, :char
55
+ t.column :char_10, :char, :limit => 10
56
+ if ActiveRecord::Base.connection.sqlserver_2005?
57
+ t.column :varchar_max, :varchar_max
58
+ t.column :varchar_max_10, :varchar_max, :limit => 10
59
+ end
60
+ end
61
+
62
+ create_table :sql_server_binary_types, :force => true do |t|
63
+ # TODO: Add some different native binary types and test.
64
+ end
65
+
66
+ execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'customers_view') DROP VIEW customers_view"
67
+ execute <<-CUSTOMERSVIEW
68
+ CREATE VIEW customers_view AS
69
+ SELECT id, name, balance
70
+ FROM customers
71
+ CUSTOMERSVIEW
72
+
73
+ execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'string_defaults_view') DROP VIEW string_defaults_view"
74
+ execute <<-STRINGDEFAULTSVIEW
75
+ CREATE VIEW string_defaults_view AS
76
+ SELECT id, string_with_pretend_null_one as pretend_null
77
+ FROM string_defaults
78
+ STRINGDEFAULTSVIEW
79
+
80
+ execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'string_defaults_big_view') DROP VIEW string_defaults_big_view"
81
+ execute <<-STRINGDEFAULTSBIGVIEW
82
+ CREATE VIEW string_defaults_big_view AS
83
+ SELECT id, string_with_pretend_null_one as pretend_null
84
+ /*#{'x'*4000}}*/
85
+ FROM string_defaults
86
+ STRINGDEFAULTSBIGVIEW
87
+
88
+ end