activerecord-sqlserver-adapter 2.3.24 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +5 -108
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +33 -61
  4. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +57 -0
  5. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +57 -0
  6. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  7. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +336 -0
  8. data/lib/active_record/connection_adapters/sqlserver/errors.rb +33 -0
  9. data/lib/active_record/connection_adapters/sqlserver/query_cache.rb +17 -0
  10. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +61 -0
  11. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +373 -0
  12. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +131 -1121
  13. data/lib/arel/engines/sql/compilers/sqlserver_compiler.rb +267 -0
  14. metadata +26 -76
  15. data/RUNNING_UNIT_TESTS +0 -31
  16. data/Rakefile +0 -60
  17. data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/active_record.rb +0 -151
  18. data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/odbc.rb +0 -40
  19. data/test/cases/aaaa_create_tables_test_sqlserver.rb +0 -19
  20. data/test/cases/adapter_test_sqlserver.rb +0 -755
  21. data/test/cases/attribute_methods_test_sqlserver.rb +0 -33
  22. data/test/cases/basics_test_sqlserver.rb +0 -86
  23. data/test/cases/calculations_test_sqlserver.rb +0 -20
  24. data/test/cases/column_test_sqlserver.rb +0 -354
  25. data/test/cases/connection_test_sqlserver.rb +0 -148
  26. data/test/cases/eager_association_test_sqlserver.rb +0 -42
  27. data/test/cases/execute_procedure_test_sqlserver.rb +0 -35
  28. data/test/cases/inheritance_test_sqlserver.rb +0 -28
  29. data/test/cases/method_scoping_test_sqlserver.rb +0 -28
  30. data/test/cases/migration_test_sqlserver.rb +0 -108
  31. data/test/cases/named_scope_test_sqlserver.rb +0 -21
  32. data/test/cases/offset_and_limit_test_sqlserver.rb +0 -108
  33. data/test/cases/pessimistic_locking_test_sqlserver.rb +0 -125
  34. data/test/cases/query_cache_test_sqlserver.rb +0 -24
  35. data/test/cases/schema_dumper_test_sqlserver.rb +0 -72
  36. data/test/cases/specific_schema_test_sqlserver.rb +0 -154
  37. data/test/cases/sqlserver_helper.rb +0 -140
  38. data/test/cases/table_name_test_sqlserver.rb +0 -38
  39. data/test/cases/transaction_test_sqlserver.rb +0 -93
  40. data/test/cases/unicode_test_sqlserver.rb +0 -54
  41. data/test/cases/validations_test_sqlserver.rb +0 -18
  42. data/test/connections/native_sqlserver/connection.rb +0 -26
  43. data/test/connections/native_sqlserver_odbc/connection.rb +0 -28
  44. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +0 -11
  45. data/test/schema/sqlserver_specific_schema.rb +0 -113
@@ -1,125 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/person'
3
- require 'models/reader'
4
-
5
- class PessimisticLockingTestSqlserver < ActiveRecord::TestCase
6
-
7
- self.use_transactional_fixtures = false
8
- fixtures :people, :readers
9
-
10
- def setup
11
- Person.columns; Reader.columns # Avoid introspection queries during tests.
12
- end
13
-
14
- context 'For simple finds with default lock option' do
15
-
16
- should 'lock with simple find' do
17
- assert_nothing_raised do
18
- Person.transaction do
19
- Person.find 1, :lock => true
20
- end
21
- end
22
- end
23
-
24
- should 'lock with scoped find' do
25
- assert_nothing_raised do
26
- Person.transaction do
27
- Person.with_scope(:find => { :lock => true }) do
28
- Person.find 1
29
- end
30
- end
31
- end
32
- end
33
-
34
- should 'lock with eager find' do
35
- assert_nothing_raised do
36
- Person.transaction do
37
- Person.find 1, :include => :readers, :lock => true
38
- end
39
- end
40
- end
41
-
42
- should 'reload with lock when #lock! called' do
43
- assert_nothing_raised do
44
- Person.transaction do
45
- person = Person.find 1
46
- old, person.first_name = person.first_name, 'fooman'
47
- person.lock!
48
- assert_equal old, person.first_name
49
- end
50
- end
51
- end
52
-
53
- should 'simply add lock to find all' do
54
- assert_sql %r|SELECT \* FROM \[people\] WITH \(NOLOCK\)| do
55
- Person.all(:lock => 'WITH (NOLOCK)')
56
- end
57
- end
58
-
59
- end
60
-
61
- context 'For paginated finds' do
62
-
63
- setup do
64
- 20.times { |n| Person.create!(:first_name => "Thing_#{n}") }
65
- end
66
-
67
- should 'cope with un-locked paginated results' do
68
- tally_not_locked = %r|SELECT count\(\*\) as TotalRows from \(SELECT TOP 1000000000 \* FROM \[people\]\s+WITH \(NOLOCK\) \) tally|
69
- inner_tmp_not_locked = %r|SELECT TOP 15 \* FROM \[people\] WITH \(NOLOCK\)|
70
- # Currently association limiting is not locked like the parent.
71
- association_limiting_not_locked = %r|SELECT \[readers\]\.\* FROM \[readers\] WITH \(NOLOCK\) WHERE \(\[readers\]\.person_id IN \(1,2,3,4,5\)\)|
72
- assert_sql(tally_not_locked,inner_tmp_not_locked) do
73
- Person.all(:include => :readers, :lock => 'WITH (NOLOCK)', :limit => 5, :offset => 10)
74
- end
75
- end
76
-
77
- end
78
-
79
-
80
- context 'For dueling concurrent connections' do
81
-
82
- use_concurrent_connections
83
-
84
- should 'no locks does not wait' do
85
- first, second = duel { Person.find 1 }
86
- assert first.end > second.end
87
- end
88
-
89
- should 'that second lock waits' do
90
- assert [0.2, 1, 5].any? { |zzz|
91
- first, second = duel(zzz) { Person.find 1, :lock => true }
92
- second.end > first.end
93
- }
94
- end
95
-
96
- end
97
-
98
-
99
- protected
100
-
101
- def duel(zzz = 5)
102
- t0, t1, t2, t3 = nil, nil, nil, nil
103
- a = Thread.new do
104
- t0 = Time.now
105
- Person.transaction do
106
- yield
107
- sleep zzz # block thread 2 for zzz seconds
108
- end
109
- t1 = Time.now
110
- end
111
- b = Thread.new do
112
- sleep zzz / 2.0 # ensure thread 1 tx starts first
113
- t2 = Time.now
114
- Person.transaction { yield }
115
- t3 = Time.now
116
- end
117
- a.join
118
- b.join
119
- assert t1 > t0 + zzz
120
- assert t2 > t0
121
- assert t3 > t2
122
- [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
123
- end
124
-
125
- end
@@ -1,24 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/task'
3
-
4
- class QueryCacheTestSqlserver < ActiveRecord::TestCase
5
- end
6
-
7
- class QueryCacheTest < ActiveRecord::TestCase
8
-
9
- COERCED_TESTS = [:test_cache_does_not_wrap_string_results_in_arrays]
10
-
11
- include SqlserverCoercedTest
12
-
13
- fixtures :tasks
14
-
15
-
16
- def test_coerced_test_cache_does_not_wrap_string_results_in_arrays
17
- Task.cache do
18
- assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
19
- end
20
- end
21
-
22
- end
23
-
24
-
@@ -1,72 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
-
3
- class SchemaDumperTestSqlserver < ActiveRecord::TestCase
4
-
5
- setup :find_all_tables
6
-
7
- context 'For primary keys' do
8
-
9
- should 'honor nonstandards' do
10
- table_dump('movies') do |output|
11
- match = output.match(%r{create_table "movies"(.*)do})
12
- assert_not_nil(match, "nonstandardpk table not found")
13
- assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
14
- end
15
- end
16
-
17
- end
18
-
19
- context 'For integers' do
20
-
21
- should 'include limit constraint that match logic for smallint and bigint in #extract_limit' do
22
- table_dump('integer_limits') do |output|
23
- assert_match %r{c_int_1.*:limit => 2}, output
24
- assert_match %r{c_int_2.*:limit => 2}, output
25
- assert_match %r{c_int_3.*}, output
26
- assert_match %r{c_int_4.*}, output
27
- assert_no_match %r{c_int_3.*:limit}, output
28
- assert_no_match %r{c_int_4.*:limit}, output
29
- assert_match %r{c_int_5.*:limit => 8}, output
30
- assert_match %r{c_int_6.*:limit => 8}, output
31
- assert_match %r{c_int_7.*:limit => 8}, output
32
- assert_match %r{c_int_8.*:limit => 8}, output
33
- end
34
- end
35
-
36
- end
37
-
38
- context 'For strings' do
39
-
40
- should 'have varchar(max) dumped as text' do
41
- table_dump('sql_server_strings') do |output|
42
- assert_match %r{t.text.*varchar_max}, output
43
- end
44
- end if sqlserver_2005? || sqlserver_2008?
45
-
46
- end
47
-
48
-
49
-
50
-
51
- private
52
-
53
- def find_all_tables
54
- @all_tables ||= ActiveRecord::Base.connection.tables
55
- end
56
-
57
- def standard_dump(ignore_tables = [])
58
- stream = StringIO.new
59
- ActiveRecord::SchemaDumper.ignore_tables = [*ignore_tables]
60
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
61
- stream.string
62
- end
63
-
64
- def table_dump(*table_names)
65
- stream = StringIO.new
66
- ActiveRecord::SchemaDumper.ignore_tables = @all_tables-table_names
67
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
68
- yield stream.string
69
- stream.string
70
- end
71
-
72
- end
@@ -1,154 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
-
3
- class StringDefault < ActiveRecord::Base; end;
4
- class SqlServerEdgeSchema < ActiveRecord::Base
5
- attr_accessor :new_id_setting
6
- before_create :set_new_id
7
- protected
8
- def set_new_id
9
- self[:guid_newid] ||= connection.newid_function if new_id_setting
10
- true
11
- end
12
- end
13
-
14
- class SpecificSchemaTestSqlserver < ActiveRecord::TestCase
15
-
16
- should 'quote table names properly even when they are views' do
17
- obj = SqlServerQuotedTable.create!
18
- assert_nothing_raised { SqlServerQuotedTable.first }
19
- obj = SqlServerQuotedView1.create!
20
- assert_nothing_raised { SqlServerQuotedView1.first }
21
- obj = SqlServerQuotedView2.create!
22
- assert_nothing_raised { SqlServerQuotedView2.first }
23
- end
24
-
25
- should 'cope with multi line defaults' do
26
- default = StringDefault.new
27
- assert_equal "Some long default with a\nnew line.", default.string_with_multiline_default
28
- end
29
-
30
- should 'default strings before save' do
31
- default = StringDefault.new
32
- assert_equal nil, default.string_with_null_default
33
- assert_equal 'null', default.string_with_pretend_null_one
34
- assert_equal '(null)', default.string_with_pretend_null_two
35
- assert_equal 'NULL', default.string_with_pretend_null_three
36
- assert_equal '(NULL)', default.string_with_pretend_null_four
37
- assert_equal '(3)', default.string_with_pretend_paren_three
38
- end
39
-
40
- should 'default strings after save' do
41
- default = StringDefault.create
42
- assert_equal nil, default.string_with_null_default
43
- assert_equal 'null', default.string_with_pretend_null_one
44
- assert_equal '(null)', default.string_with_pretend_null_two
45
- assert_equal 'NULL', default.string_with_pretend_null_three
46
- assert_equal '(NULL)', default.string_with_pretend_null_four
47
- end
48
-
49
- context 'Testing edge case schemas' do
50
-
51
- setup do
52
- @edge_class = SqlServerEdgeSchema
53
- end
54
-
55
- context 'with description column' do
56
-
57
- setup do
58
- @da = @edge_class.create! :description => 'A'
59
- @db = @edge_class.create! :description => 'B'
60
- @dc = @edge_class.create! :description => 'C'
61
- end
62
-
63
- teardown { @edge_class.delete_all }
64
-
65
- should 'allow all sorts of ordering without adapter munging it up' do
66
- assert_equal ['A','B','C'], @edge_class.all(:order => 'description').map(&:description)
67
- assert_equal ['A','B','C'], @edge_class.all(:order => 'description asc').map(&:description)
68
- assert_equal ['A','B','C'], @edge_class.all(:order => 'description ASC').map(&:description)
69
- assert_equal ['C','B','A'], @edge_class.all(:order => 'description desc').map(&:description)
70
- assert_equal ['C','B','A'], @edge_class.all(:order => 'description DESC').map(&:description)
71
- end
72
-
73
- end
74
-
75
- context 'with bigint column' do
76
-
77
- setup do
78
- @b5k = 5000
79
- @bi5k = @edge_class.create! :bigint => @b5k, :description => 'Five Thousand'
80
- @bnum = 9_000_000_000_000_000_000
81
- @bimjr = @edge_class.create! :bigint => @bnum, :description => 'Close to max bignum'
82
- end
83
-
84
- should 'can find by biginit' do
85
- assert_equal @bi5k, @edge_class.find_by_bigint(@b5k)
86
- assert_equal @b5k, @edge_class.find(:first, :select => 'bigint', :conditions => {:bigint => @b5k}).bigint
87
- assert_equal @bimjr, @edge_class.find_by_bigint(@bnum)
88
- assert_equal @bnum, @edge_class.find(:first, :select => 'bigint', :conditions => {:bigint => @bnum}).bigint
89
- end
90
-
91
- end
92
-
93
- context 'with tinyint column' do
94
-
95
- setup do
96
- @tiny1 = @edge_class.create! :tinyint => 1
97
- @tiny255 = @edge_class.create! :tinyint => 255
98
- end
99
-
100
- should 'not treat tinyint like boolean as mysql does' do
101
- assert_equal 1, @edge_class.find_by_tinyint(1).tinyint
102
- assert_equal 255, @edge_class.find_by_tinyint(255).tinyint
103
- end
104
-
105
- should 'throw an error when going out of our tiny int bounds' do
106
- assert_raise(ActiveRecord::StatementInvalid) { @edge_class.create! :tinyint => 256 }
107
- end
108
-
109
- end
110
-
111
- context 'with uniqueidentifier column' do
112
-
113
- setup do
114
- @newid = ActiveRecord::Base.connection.newid_function
115
- assert_guid @newid
116
- end
117
-
118
- should 'allow a simple insert and read of a column without a default function' do
119
- obj = @edge_class.create! :guid => @newid
120
- assert_equal @newid, @edge_class.find(obj.id).guid
121
- end
122
-
123
- should 'record the default function name in the column definition but still show a nil real default, will use one day for insert/update' do
124
- newid_column = @edge_class.columns_hash['guid_newid']
125
- assert newid_column.default_function.present?
126
- assert_nil newid_column.default
127
- assert_equal 'newid()', newid_column.default_function
128
- unless ActiveRecord::Base.connection.sqlserver_2000?
129
- newseqid_column = @edge_class.columns_hash['guid_newseqid']
130
- assert newseqid_column.default_function.present?
131
- assert_nil newseqid_column.default
132
- assert_equal 'newsequentialid()', newseqid_column.default_function
133
- end
134
- end
135
-
136
- should 'use model callback to set get a new guid' do
137
- obj = @edge_class.new
138
- obj.new_id_setting = true
139
- obj.save!
140
- assert_guid obj.guid_newid
141
- end
142
-
143
- end
144
-
145
- end
146
-
147
-
148
- protected
149
-
150
- def assert_guid(guid)
151
- assert_match %r|\w{8}-\w{4}-\w{4}-\w{4}-\w{12}|, guid
152
- end
153
-
154
- end
@@ -1,140 +0,0 @@
1
-
2
- SQLSERVER_TEST_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'..'))
3
- SQLSERVER_ASSETS_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'assets'))
4
- SQLSERVER_FIXTURES_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'fixtures'))
5
- SQLSERVER_MIGRATIONS_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'migrations'))
6
- SQLSERVER_SCHEMA_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'schema'))
7
- ACTIVERECORD_TEST_ROOT = File.expand_path(File.join(ENV['RAILS_SOURCE'],'activerecord','test'))
8
-
9
- require 'rubygems'
10
- require 'bundler'
11
- Bundler.setup
12
- require 'shoulda'
13
- require 'mocha'
14
- begin ; require 'ruby-debug' ; rescue LoadError ; end
15
- [ File.expand_path(File.join(File.dirname(__FILE__),'..','..','test')),
16
- File.expand_path(File.join(File.dirname(__FILE__),'..','..','test','connections','native_sqlserver_odbc')),
17
- File.expand_path(File.join(ENV['RAILS_SOURCE'],'activerecord','test'))
18
- ].each{ |lib| $:.unshift(lib) unless $:.include?(lib) } if ENV['TM_DIRECTORY']
19
- require 'cases/helper'
20
- require 'models/topic'
21
- require 'active_record/version'
22
-
23
- GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly?)
24
-
25
- ActiveRecord::Migration.verbose = false
26
- ActiveRecord::ConnectionAdapters::SQLServerAdapter.log_info_schema_queries = true
27
-
28
- # Defining our classes in one place as well as soem core tests that need coercing date/time types.
29
-
30
- class TableWithRealColumn < ActiveRecord::Base; end
31
- class FkTestHasFk < ActiveRecord::Base ; end
32
- class FkTestHasPk < ActiveRecord::Base ; end
33
- class NumericData < ActiveRecord::Base ; self.table_name = 'numeric_data' ; end
34
- class FloatData < ActiveRecord::Base ; self.table_name = 'float_data' ; end
35
- class CustomersView < ActiveRecord::Base ; self.table_name = 'customers_view' ; end
36
- class StringDefaultsView < ActiveRecord::Base ; self.table_name = 'string_defaults_view' ; end
37
- class StringDefaultsBigView < ActiveRecord::Base ; self.table_name = 'string_defaults_big_view' ; end
38
- class SqlServerQuotedTable < ActiveRecord::Base ; self.table_name = 'quoted-table' ; end
39
- class SqlServerQuotedView1 < ActiveRecord::Base ; self.table_name = 'quoted-view1' ; end
40
- class SqlServerQuotedView2 < ActiveRecord::Base ; self.table_name = 'quoted-view2' ; end
41
- class SqlServerUnicode < ActiveRecord::Base ; end
42
- class SqlServerString < ActiveRecord::Base ; end
43
- class SqlServerChronic < ActiveRecord::Base
44
- coerce_sqlserver_date :date
45
- coerce_sqlserver_time :time
46
- default_timezone = :utc
47
- end
48
- class Topic < ActiveRecord::Base
49
- coerce_sqlserver_date :last_read
50
- coerce_sqlserver_time :bonus_time
51
- end
52
- class Person < ActiveRecord::Base
53
- coerce_sqlserver_date :favorite_day
54
- end
55
-
56
- # A module that we can include in classes where we want to override an active record test.
57
-
58
- module SqlserverCoercedTest
59
- def self.included(base)
60
- base.extend ClassMethods
61
- end
62
- module ClassMethods
63
- def coerced_tests
64
- self.const_get(:COERCED_TESTS) rescue nil
65
- end
66
- def method_added(method)
67
- if coerced_tests && coerced_tests.include?(method)
68
- undef_method(method)
69
- STDOUT.puts("Undefined coerced test: #{self.name}##{method}")
70
- end
71
- end
72
- end
73
- end
74
-
75
- # Set weather to test unicode string defaults or not. Used from rake task.
76
-
77
- if ENV['ENABLE_DEFAULT_UNICODE_TYPES'] != 'false'
78
- puts "With enabled unicode string types"
79
- ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types = true
80
- end
81
-
82
- # Change the text database type to support ActiveRecord's tests for = on text columns which
83
- # is not supported in SQL Server text columns, so use varchar(8000) instead.
84
-
85
- if ActiveRecord::Base.connection.sqlserver_2000?
86
- if ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types
87
- ActiveRecord::ConnectionAdapters::SQLServerAdapter.native_text_database_type = 'nvarchar(4000)'
88
- else
89
- ActiveRecord::ConnectionAdapters::SQLServerAdapter.native_text_database_type = 'varchar(8000)'
90
- end
91
- end
92
-
93
- # Our changes/additions to ActiveRecord test helpers specific for SQL Server.
94
-
95
- ActiveRecord::Base.connection.class.class_eval do
96
- IGNORED_SQL << %r|SELECT SCOPE_IDENTITY| << %r{INFORMATION_SCHEMA\.(TABLES|VIEWS|COLUMNS)}
97
- IGNORED_SQL << %r|SELECT @@IDENTITY| << %r|SELECT @@ROWCOUNT| << %r|SELECT @@version| << %r|SELECT @@TRANCOUNT|
98
- end
99
-
100
- ActiveRecord::ConnectionAdapters::SQLServerAdapter.class_eval do
101
- def raw_select_with_query_record(sql, name=nil, options={})
102
- $queries_executed ||= []
103
- $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
104
- raw_select_without_query_record(sql,name,options)
105
- end
106
- alias_method_chain :raw_select, :query_record
107
- end
108
-
109
- module ActiveRecord
110
- class TestCase < ActiveSupport::TestCase
111
- class << self
112
- def connection_mode_dblib? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :dblib ; end
113
- def connection_mode_odbc? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :odbc ; end
114
- def connection_mode_adonet? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :adonet ; end
115
- def sqlserver_2000? ; ActiveRecord::Base.connection.sqlserver_2000? ; end
116
- def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
117
- def sqlserver_2008? ; ActiveRecord::Base.connection.sqlserver_2008? ; end
118
- def ruby_19? ; RUBY_VERSION >= '1.9' ; end
119
- end
120
- def assert_sql(*patterns_to_match)
121
- $queries_executed = []
122
- yield
123
- ensure
124
- failed_patterns = []
125
- patterns_to_match.each do |pattern|
126
- failed_patterns << pattern unless $queries_executed.any?{ |sql| pattern === sql }
127
- end
128
- assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found in:\n#{$queries_executed.inspect}"
129
- end
130
- def connection_mode_dblib? ; self.class.connection_mode_dblib? ; end
131
- def connection_mode_odbc? ; self.class.connection_mode_odbc? ; end
132
- def connection_mode_adonet? ; self.class.connection_mode_adonet? ; end
133
- def sqlserver_2000? ; self.class.sqlserver_2000? ; end
134
- def sqlserver_2005? ; self.class.sqlserver_2005? ; end
135
- def sqlserver_2008? ; self.class.sqlserver_2008? ; end
136
- def ruby_19? ; self.class.ruby_19? ; end
137
- end
138
- end
139
-
140
-