artpop-2000-2005-adapter 2.2.15

Sign up to get free protection for your applications and to get access to all the features.
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 +1014 -0
  10. data/lib/core_ext/active_record.rb +133 -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