activerecord-jdbcsqlserver-adapter 50.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +27 -0
- data/CHANGELOG.md +124 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/Dockerfile +20 -0
- data/Gemfile +77 -0
- data/Guardfile +29 -0
- data/MIT-LICENSE +20 -0
- data/RAILS5-TODO.md +5 -0
- data/README.md +93 -0
- data/RUNNING_UNIT_TESTS.md +96 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/activerecord-jdbcsqlserver-adapter.gemspec +21 -0
- data/appveyor.yml +39 -0
- data/docker-compose.ci.yml +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/date_time.rb +58 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +47 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +362 -0
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +67 -0
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +192 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +99 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +34 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +517 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +112 -0
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +64 -0
- data/lib/active_record/connection_adapters/sqlserver/type.rb +49 -0
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +32 -0
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +61 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +71 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +23 -0
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +15 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +29 -0
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +68 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +93 -0
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +24 -0
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +146 -0
- data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +445 -0
- data/lib/active_record/connection_adapters/sqlserver_column.rb +28 -0
- data/lib/active_record/jdbc_sqlserver_connection_methods.rb +31 -0
- data/lib/active_record/sqlserver_base.rb +16 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
- data/lib/activerecord-jdbcsqlserver-adapter.rb +24 -0
- data/lib/activerecord-sqlserver-adapter.rb +1 -0
- data/lib/arel/visitors/sqlserver.rb +205 -0
- data/lib/arel_sqlserver.rb +3 -0
- data/test/appveyor/dbsetup.ps1 +27 -0
- data/test/appveyor/dbsetup.sql +11 -0
- data/test/bin/wait-for.sh +79 -0
- data/test/cases/adapter_test_sqlserver.rb +430 -0
- data/test/cases/coerced_tests.rb +845 -0
- data/test/cases/column_test_sqlserver.rb +812 -0
- data/test/cases/connection_test_sqlserver.rb +71 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +45 -0
- data/test/cases/fetch_test_sqlserver.rb +57 -0
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
- data/test/cases/helper_sqlserver.rb +44 -0
- data/test/cases/index_test_sqlserver.rb +47 -0
- data/test/cases/json_test_sqlserver.rb +32 -0
- data/test/cases/migration_test_sqlserver.rb +61 -0
- data/test/cases/order_test_sqlserver.rb +147 -0
- data/test/cases/pessimistic_locking_test_sqlserver.rb +94 -0
- data/test/cases/rake_test_sqlserver.rb +169 -0
- data/test/cases/schema_dumper_test_sqlserver.rb +234 -0
- data/test/cases/schema_test_sqlserver.rb +54 -0
- data/test/cases/scratchpad_test_sqlserver.rb +8 -0
- data/test/cases/showplan_test_sqlserver.rb +65 -0
- data/test/cases/specific_schema_test_sqlserver.rb +180 -0
- data/test/cases/transaction_test_sqlserver.rb +91 -0
- data/test/cases/utils_test_sqlserver.rb +129 -0
- data/test/cases/uuid_test_sqlserver.rb +49 -0
- data/test/config.yml +38 -0
- data/test/debug.rb +14 -0
- data/test/fixtures/1px.gif +0 -0
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
- data/test/models/sqlserver/booking.rb +3 -0
- data/test/models/sqlserver/customers_view.rb +3 -0
- data/test/models/sqlserver/datatype.rb +3 -0
- data/test/models/sqlserver/datatype_migration.rb +8 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -0
- data/test/models/sqlserver/dot_table_name.rb +3 -0
- data/test/models/sqlserver/edge_schema.rb +13 -0
- data/test/models/sqlserver/fk_has_fk.rb +3 -0
- data/test/models/sqlserver/fk_has_pk.rb +3 -0
- data/test/models/sqlserver/natural_pk_data.rb +4 -0
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
- data/test/models/sqlserver/no_pk_data.rb +3 -0
- data/test/models/sqlserver/object_default.rb +3 -0
- data/test/models/sqlserver/quoted_table.rb +7 -0
- data/test/models/sqlserver/quoted_view_1.rb +3 -0
- data/test/models/sqlserver/quoted_view_2.rb +3 -0
- data/test/models/sqlserver/sst_memory.rb +3 -0
- data/test/models/sqlserver/string_default.rb +3 -0
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
- data/test/models/sqlserver/string_defaults_view.rb +3 -0
- data/test/models/sqlserver/tinyint_pk.rb +3 -0
- data/test/models/sqlserver/upper.rb +3 -0
- data/test/models/sqlserver/uppered.rb +3 -0
- data/test/models/sqlserver/uuid.rb +3 -0
- data/test/schema/datatypes/2012.sql +55 -0
- data/test/schema/enable-in-memory-oltp.sql +81 -0
- data/test/schema/sqlserver_specific_schema.rb +238 -0
- data/test/support/coerceable_test_sqlserver.rb +49 -0
- data/test/support/connection_reflection.rb +34 -0
- data/test/support/load_schema_sqlserver.rb +29 -0
- data/test/support/minitest_sqlserver.rb +1 -0
- data/test/support/paths_sqlserver.rb +50 -0
- data/test/support/rake_helpers.rb +41 -0
- data/test/support/sql_counter_sqlserver.rb +28 -0
- data/test/support/test_in_memory_oltp.rb +15 -0
- metadata +310 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
require 'models/reply'
|
|
3
|
+
require 'models/topic'
|
|
4
|
+
|
|
5
|
+
class ConnectionTestSQLServer < ActiveRecord::TestCase
|
|
6
|
+
|
|
7
|
+
self.use_transactional_tests = false
|
|
8
|
+
|
|
9
|
+
fixtures :topics, :accounts
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
connection.reconnect!
|
|
13
|
+
assert connection.active?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'affect rows' do
|
|
17
|
+
topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
|
|
18
|
+
updated = Topic.update(topic_data.keys, topic_data.values)
|
|
19
|
+
assert_equal 2, updated.size
|
|
20
|
+
assert_equal "1 updated", Topic.find(1).content
|
|
21
|
+
assert_equal "2 updated", Topic.find(2).content
|
|
22
|
+
assert_equal 2, Topic.delete([1, 2])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'allow usage of :database connection option to remove setting from dsn' do
|
|
26
|
+
assert_equal 'activerecord_unittest', connection.current_database
|
|
27
|
+
begin
|
|
28
|
+
connection.use_database('activerecord_unittest2')
|
|
29
|
+
assert_equal 'activerecord_unittest2', connection.current_database
|
|
30
|
+
ensure
|
|
31
|
+
connection.use_database
|
|
32
|
+
assert_equal 'activerecord_unittest', connection.current_database, 'Would default back to connection options'
|
|
33
|
+
end
|
|
34
|
+
end unless connection_sqlserver_azure?
|
|
35
|
+
|
|
36
|
+
describe 'Connection management' do
|
|
37
|
+
|
|
38
|
+
it 'set spid on connect' do
|
|
39
|
+
['Fixnum', 'Integer'].must_include connection.spid.class.name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'reset spid on disconnect!' do
|
|
43
|
+
connection.disconnect!
|
|
44
|
+
assert connection.spid.nil?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'reset the connection' do
|
|
48
|
+
connection.disconnect!
|
|
49
|
+
connection.raw_connection.must_be_nil
|
|
50
|
+
end unless defined? JRUBY_VERSION
|
|
51
|
+
|
|
52
|
+
it 'be able to disconnect and reconnect at will' do
|
|
53
|
+
disconnect_raw_connection!
|
|
54
|
+
assert !connection.active?
|
|
55
|
+
connection.reconnect!
|
|
56
|
+
assert connection.active?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def disconnect_raw_connection!
|
|
65
|
+
#case connection_options[:mode]
|
|
66
|
+
#when :dblib
|
|
67
|
+
connection.raw_connection.close #rescue nil
|
|
68
|
+
#end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
|
|
3
|
+
class ExecuteProcedureTestSQLServer < ActiveRecord::TestCase
|
|
4
|
+
|
|
5
|
+
it 'execute a simple procedure' do
|
|
6
|
+
tables = ActiveRecord::Base.execute_procedure :sp_tables
|
|
7
|
+
assert_instance_of Array, tables
|
|
8
|
+
assert tables.first.respond_to?(:keys)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'take parameter arguments' do
|
|
12
|
+
tables = ActiveRecord::Base.execute_procedure :sp_tables, 'sst_datatypes'
|
|
13
|
+
table_info = tables.first
|
|
14
|
+
assert_equal 1, tables.size
|
|
15
|
+
assert_equal (ENV['ARUNIT_DB_NAME'] || 'activerecord_unittest'), table_info['TABLE_QUALIFIER'], "Table Info: #{table_info.inspect}"
|
|
16
|
+
assert_equal 'TABLE', table_info['TABLE_TYPE'], "Table Info: #{table_info.inspect}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'allow multiple result sets to be returned' do
|
|
20
|
+
skip 'For whatever reason, this stored procedure is only returning 1 result so this test does not work' if defined? JRUBY_VERSION
|
|
21
|
+
results1, results2 = ActiveRecord::Base.execute_procedure('sp_helpconstraint','accounts')
|
|
22
|
+
assert_instance_of Array, results1
|
|
23
|
+
assert results1.first.respond_to?(:keys)
|
|
24
|
+
assert results1.first['Object Name']
|
|
25
|
+
assert_instance_of Array, results2
|
|
26
|
+
assert results2.first.respond_to?(:keys)
|
|
27
|
+
assert results2.first['constraint_name']
|
|
28
|
+
assert results2.first['constraint_type']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'take named parameter arguments' do
|
|
32
|
+
tables = ActiveRecord::Base.execute_procedure :sp_tables, table_name: 'tables', table_owner: 'sys'
|
|
33
|
+
table_info = tables.first
|
|
34
|
+
assert_equal 1, tables.size
|
|
35
|
+
assert_equal (ENV['ARUNIT_DB_NAME'] || 'activerecord_unittest'), table_info['TABLE_QUALIFIER'], "Table Info: #{table_info.inspect}"
|
|
36
|
+
assert_equal 'VIEW', table_info['TABLE_TYPE'], "Table Info: #{table_info.inspect}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'uses the proper timezone' do
|
|
40
|
+
date_proc = connection.execute_procedure('my_getutcdate').first['utcdate']
|
|
41
|
+
date_base = connection.select_value('select GETUTCDATE()')
|
|
42
|
+
assert_equal date_base.change(usec: 0), date_proc.change(usec: 0)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
require 'models/book'
|
|
3
|
+
|
|
4
|
+
class FetchTestSqlserver < ActiveRecord::TestCase
|
|
5
|
+
|
|
6
|
+
let(:books) { @books }
|
|
7
|
+
|
|
8
|
+
before { create_10_books }
|
|
9
|
+
|
|
10
|
+
it 'work with fully qualified table and columns in select' do
|
|
11
|
+
books = Book.select('books.id, books.name').limit(3).offset(5)
|
|
12
|
+
assert_equal Book.all[5,3].map(&:id), books.map(&:id)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe 'count' do
|
|
16
|
+
|
|
17
|
+
it 'gauntlet' do
|
|
18
|
+
books[0].destroy
|
|
19
|
+
books[1].destroy
|
|
20
|
+
books[2].destroy
|
|
21
|
+
assert_equal 7, Book.count
|
|
22
|
+
assert_equal 1, Book.limit(1).offset(1).count
|
|
23
|
+
assert_equal 1, Book.limit(1).offset(5).count
|
|
24
|
+
assert_equal 1, Book.limit(1).offset(6).count
|
|
25
|
+
assert_equal 0, Book.limit(1).offset(7).count
|
|
26
|
+
assert_equal 3, Book.limit(3).offset(4).count
|
|
27
|
+
assert_equal 2, Book.limit(3).offset(5).count
|
|
28
|
+
assert_equal 1, Book.limit(3).offset(6).count
|
|
29
|
+
assert_equal 0, Book.limit(3).offset(7).count
|
|
30
|
+
assert_equal 0, Book.limit(3).offset(8).count
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'order' do
|
|
36
|
+
|
|
37
|
+
it 'gauntlet' do
|
|
38
|
+
Book.where(name:'Name-10').delete_all
|
|
39
|
+
Book.order(:name).limit(1).offset(1).map(&:name).must_equal ['Name-2']
|
|
40
|
+
Book.order(:name).limit(2).offset(2).map(&:name).must_equal ['Name-3', 'Name-4']
|
|
41
|
+
Book.order(:name).limit(2).offset(7).map(&:name).must_equal ['Name-8', 'Name-9']
|
|
42
|
+
Book.order(:name).limit(3).offset(7).map(&:name).must_equal ['Name-8', 'Name-9']
|
|
43
|
+
Book.order(:name).limit(3).offset(9).map(&:name).must_equal []
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
def create_10_books
|
|
52
|
+
Book.delete_all
|
|
53
|
+
@books = (1..10).map { |i| Book.create! name: "Name-#{i}" }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
|
|
3
|
+
class FullyQualifiedIdentifierTestSQLServer < ActiveRecord::TestCase
|
|
4
|
+
|
|
5
|
+
describe 'local server' do
|
|
6
|
+
|
|
7
|
+
it 'should use table name in select projections' do
|
|
8
|
+
table = Arel::Table.new(:table)
|
|
9
|
+
expected_sql = "SELECT [table].[name] FROM [table]"
|
|
10
|
+
assert_equal expected_sql, table.project(table[:name]).to_sql
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe 'remote server' do
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
connection_options[:database_prefix] = "[my.server].db.schema."
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
after do
|
|
22
|
+
connection_options.delete :database_prefix
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'should use fully qualified table name in select from clause' do
|
|
26
|
+
table = Arel::Table.new(:table)
|
|
27
|
+
expected_sql = "SELECT * FROM [my.server].[db].[schema].[table]"
|
|
28
|
+
assert_equal expected_sql, table.project(Arel.star).to_sql
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should not use fully qualified table name in select projections' do
|
|
32
|
+
table = Arel::Table.new(:table)
|
|
33
|
+
expected_sql = "SELECT [table].[name] FROM [my.server].[db].[schema].[table]"
|
|
34
|
+
assert_equal expected_sql, table.project(table[:name]).to_sql
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should not use fully qualified table name in where clause' do
|
|
38
|
+
table = Arel::Table.new(:table)
|
|
39
|
+
expected_sql = "SELECT * FROM [my.server].[db].[schema].[table] WHERE [table].[id] = 42"
|
|
40
|
+
quietly { assert_equal expected_sql, table.project(Arel.star).where(table[:id].eq(42)).to_sql }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'should not use fully qualified table name in order clause' do
|
|
44
|
+
table = Arel::Table.new(:table)
|
|
45
|
+
expected_sql = "SELECT * FROM [my.server].[db].[schema].[table] ORDER BY [table].[name]"
|
|
46
|
+
assert_equal expected_sql, table.project(Arel.star).order(table[:name]).to_sql
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should use fully qualified table name in insert statement' do
|
|
50
|
+
manager = Arel::InsertManager.new
|
|
51
|
+
manager.into Arel::Table.new(:table)
|
|
52
|
+
manager.values = manager.create_values [Arel.sql('*')], %w{ a }
|
|
53
|
+
expected_sql = "INSERT INTO [my.server].[db].[schema].[table] VALUES (*)"
|
|
54
|
+
quietly { assert_equal expected_sql, manager.to_sql }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'should use fully qualified table name in update statement' do
|
|
58
|
+
table = Arel::Table.new(:table)
|
|
59
|
+
manager = Arel::UpdateManager.new
|
|
60
|
+
manager.table(table).where(table[:id].eq(42))
|
|
61
|
+
manager.set([[table[:name], "Bob"]])
|
|
62
|
+
expected_sql = "UPDATE [my.server].[db].[schema].[table] SET [name] = N'Bob' WHERE [table].[id] = 42"
|
|
63
|
+
quietly { assert_equal expected_sql, manager.to_sql }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should use fully qualified table name in delete statement' do
|
|
67
|
+
table = Arel::Table.new(:table)
|
|
68
|
+
manager = Arel::DeleteManager.new
|
|
69
|
+
manager.from(table).where(table[:id].eq(42))
|
|
70
|
+
expected_sql = "DELETE FROM [my.server].[db].[schema].[table] WHERE [table].[id] = 42"
|
|
71
|
+
quietly { assert_equal expected_sql, manager.to_sql }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'support/paths_sqlserver'
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
Bundler.require :default, :development
|
|
4
|
+
require 'pry'
|
|
5
|
+
require 'support/minitest_sqlserver'
|
|
6
|
+
require 'support/test_in_memory_oltp'
|
|
7
|
+
require 'cases/helper'
|
|
8
|
+
require 'support/load_schema_sqlserver'
|
|
9
|
+
require 'support/coerceable_test_sqlserver'
|
|
10
|
+
require 'support/sql_counter_sqlserver'
|
|
11
|
+
require 'support/connection_reflection'
|
|
12
|
+
require 'mocha/mini_test'
|
|
13
|
+
|
|
14
|
+
module ActiveRecord
|
|
15
|
+
class TestCase < ActiveSupport::TestCase
|
|
16
|
+
|
|
17
|
+
SQLServer = ActiveRecord::ConnectionAdapters::SQLServer
|
|
18
|
+
|
|
19
|
+
include ARTest::SQLServer::CoerceableTest,
|
|
20
|
+
ARTest::SQLServer::ConnectionReflection,
|
|
21
|
+
ARTest::SQLServer::SqlCounterSqlserver,
|
|
22
|
+
ActiveSupport::Testing::Stream
|
|
23
|
+
|
|
24
|
+
let(:logger) { ActiveRecord::Base.logger }
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def host_windows?
|
|
30
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def with_use_output_inserted_disabled
|
|
34
|
+
klass = ActiveRecord::ConnectionAdapters::SQLServerAdapter
|
|
35
|
+
klass.use_output_inserted = false
|
|
36
|
+
yield
|
|
37
|
+
ensure
|
|
38
|
+
klass.use_output_inserted = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Dir["#{ARTest::SQLServer.test_root_sqlserver}/models/**/*.rb"].each { |f| require f }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
|
|
3
|
+
class IndexTestSQLServer < ActiveRecord::TestCase
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
connection.create_table(:testings) do |t|
|
|
7
|
+
t.column :foo, :string, limit: 100
|
|
8
|
+
t.column :bar, :string, limit: 100
|
|
9
|
+
t.string :first_name
|
|
10
|
+
t.string :last_name, limit: 100
|
|
11
|
+
t.string :key, limit: 100
|
|
12
|
+
t.boolean :administrator
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
after do
|
|
17
|
+
connection.drop_table :testings rescue nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'add index with order' do
|
|
21
|
+
assert_sql(/CREATE.*INDEX.*\(\[last_name\] DESC\)/i) do
|
|
22
|
+
connection.add_index 'testings', ['last_name'], order: { last_name: :desc }
|
|
23
|
+
connection.remove_index 'testings', ['last_name']
|
|
24
|
+
end
|
|
25
|
+
assert_sql(/CREATE.*INDEX.*\(\[last_name\] DESC, \[first_name\]\)/i) do
|
|
26
|
+
connection.add_index 'testings', ['last_name', 'first_name'], order: { last_name: :desc }
|
|
27
|
+
connection.remove_index 'testings', ['last_name', 'first_name']
|
|
28
|
+
end
|
|
29
|
+
assert_sql(/CREATE.*INDEX.*\(\[last_name\] DESC, \[first_name\] ASC\)/i) do
|
|
30
|
+
connection.add_index 'testings', ['last_name', 'first_name'], order: { last_name: :desc, first_name: :asc }
|
|
31
|
+
connection.remove_index 'testings', ['last_name', 'first_name']
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'add index with where' do
|
|
36
|
+
assert_sql(/CREATE.*INDEX.*\(\[last_name\]\) WHERE \[first_name\] = N'john doe'/i) do
|
|
37
|
+
connection.add_index 'testings', 'last_name', where: "[first_name] = N'john doe'"
|
|
38
|
+
connection.remove_index 'testings', 'last_name'
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'add index with expression' do
|
|
43
|
+
connection.execute "ALTER TABLE [testings] ADD [first_name_upper] AS UPPER([first_name])"
|
|
44
|
+
connection.add_index 'testings', 'first_name_upper'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
|
|
3
|
+
if ActiveRecord::Base.connection.supports_json?
|
|
4
|
+
class JsonTestSQLServer < ActiveRecord::TestCase
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
@o1 = SSTestDatatypeMigrationJson.create! json_col: { 'a' => 'a', 'b' => 'b', 'c' => 'c' }
|
|
8
|
+
@o2 = SSTestDatatypeMigrationJson.create! json_col: { 'a' => nil, 'b' => 'b', 'c' => 'c' }
|
|
9
|
+
@o3 = SSTestDatatypeMigrationJson.create! json_col: { 'x' => 1, 'y' => 2, 'z' => 3 }
|
|
10
|
+
@o4 = SSTestDatatypeMigrationJson.create! json_col: { 'array' => [1, 2, 3] }
|
|
11
|
+
@o5 = SSTestDatatypeMigrationJson.create! json_col: nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'can return and save JSON data' do
|
|
15
|
+
SSTestDatatypeMigrationJson.find(@o1.id).json_col.must_equal({ 'a' => 'a', 'b' => 'b', 'c' => 'c' })
|
|
16
|
+
@o1.json_col = { 'a' => 'a' }
|
|
17
|
+
@o1.json_col.must_equal({ 'a' => 'a' })
|
|
18
|
+
@o1.save!
|
|
19
|
+
@o1.reload.json_col.must_equal({ 'a' => 'a' })
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'can use ISJSON function' do
|
|
23
|
+
SSTestDatatypeMigrationJson.where('ISJSON(json_col) > 0').count.must_equal 4
|
|
24
|
+
SSTestDatatypeMigrationJson.where('ISJSON(json_col) IS NULL').count.must_equal 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'can use JSON_VALUE function' do
|
|
28
|
+
SSTestDatatypeMigrationJson.where("JSON_VALUE(json_col, '$.b') = 'b'").count.must_equal 2
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
require 'models/person'
|
|
3
|
+
|
|
4
|
+
class MigrationTestSQLServer < ActiveRecord::TestCase
|
|
5
|
+
|
|
6
|
+
describe 'For transactions' do
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@trans_test_table1 = 'sqlserver_trans_table1'
|
|
10
|
+
@trans_test_table2 = 'sqlserver_trans_table2'
|
|
11
|
+
@trans_tables = [@trans_test_table1,@trans_test_table2]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
after do
|
|
15
|
+
@trans_tables.each do |table_name|
|
|
16
|
+
ActiveRecord::Migration.drop_table(table_name) if connection.tables.include?(table_name)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'not create a tables if error in migrations' do
|
|
21
|
+
begin
|
|
22
|
+
migrations_dir = File.join ARTest::SQLServer.migrations_root, 'transaction_table'
|
|
23
|
+
quietly { ActiveRecord::Migrator.up(migrations_dir) }
|
|
24
|
+
rescue Exception => e
|
|
25
|
+
assert_match %r|this and all later migrations canceled|, e.message
|
|
26
|
+
end
|
|
27
|
+
connection.tables.wont_include @trans_test_table1
|
|
28
|
+
connection.tables.wont_include @trans_test_table2
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe 'For changing column' do
|
|
34
|
+
|
|
35
|
+
it 'not raise exception when column contains default constraint' do
|
|
36
|
+
lock_version_column = Person.columns_hash['lock_version']
|
|
37
|
+
assert_equal :integer, lock_version_column.type
|
|
38
|
+
assert lock_version_column.default.present?
|
|
39
|
+
assert_nothing_raised { connection.change_column 'people', 'lock_version', :string }
|
|
40
|
+
Person.reset_column_information
|
|
41
|
+
lock_version_column = Person.columns_hash['lock_version']
|
|
42
|
+
assert_equal :string, lock_version_column.type
|
|
43
|
+
assert lock_version_column.default.nil?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'not drop the default contraint if just renaming' do
|
|
47
|
+
find_default = lambda do
|
|
48
|
+
connection.execute_procedure(:sp_helpconstraint, 'sst_string_defaults', 'nomsg').select do |row|
|
|
49
|
+
row['constraint_type'] == "DEFAULT on column string_with_pretend_paren_three"
|
|
50
|
+
end.last
|
|
51
|
+
end
|
|
52
|
+
default_before = find_default.call
|
|
53
|
+
connection.change_column :sst_string_defaults, :string_with_pretend_paren_three, :string, limit: 255
|
|
54
|
+
default_after = find_default.call
|
|
55
|
+
assert default_after
|
|
56
|
+
assert_equal default_before['constraint_keys'], default_after['constraint_keys']
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
require 'cases/helper_sqlserver'
|
|
2
|
+
require 'models/post'
|
|
3
|
+
|
|
4
|
+
class OrderTestSQLServer < ActiveRecord::TestCase
|
|
5
|
+
|
|
6
|
+
fixtures :posts
|
|
7
|
+
|
|
8
|
+
it 'not mangel complex order clauses' do
|
|
9
|
+
xyz_order = "CASE WHEN [title] LIKE N'XYZ%' THEN 0 ELSE 1 END"
|
|
10
|
+
xyz_post = Post.create title: 'XYZ Post', body: 'Test cased orders.'
|
|
11
|
+
assert_equal xyz_post, Post.order(Arel.sql(xyz_order)).first
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'support column' do
|
|
15
|
+
order = "title"
|
|
16
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
17
|
+
assert_equal post1, Post.order(order).first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'support column ASC' do
|
|
21
|
+
order = "title ASC"
|
|
22
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
23
|
+
assert_equal post1, Post.order(order).first
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'support column DESC' do
|
|
27
|
+
order = "title DESC"
|
|
28
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
29
|
+
assert_equal post1, Post.order(order).first
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'support column as symbol' do
|
|
33
|
+
order = :title
|
|
34
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
35
|
+
assert_equal post1, Post.order(order).first
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'support table and column' do
|
|
39
|
+
order = "posts.title"
|
|
40
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
41
|
+
assert_equal post1, Post.order(order).first
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'support quoted column' do
|
|
45
|
+
order = "[title]"
|
|
46
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
47
|
+
assert_equal post1, Post.order(order).first
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'support quoted table and column' do
|
|
51
|
+
order = "[posts].[title]"
|
|
52
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
53
|
+
assert_equal post1, Post.order(order).first
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'support primary: column, secondary: column' do
|
|
57
|
+
order = "title DESC, body"
|
|
58
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
59
|
+
post2 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
|
60
|
+
assert_equal post1, Post.order(order).first
|
|
61
|
+
assert_equal post2, Post.order(order).second
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'support primary: table and column, secondary: column' do
|
|
65
|
+
order = "posts.title DESC, body"
|
|
66
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
67
|
+
post2 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
|
68
|
+
assert_equal post1, Post.order(order).first
|
|
69
|
+
assert_equal post2, Post.order(order).second
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'support primary: case expression, secondary: column' do
|
|
73
|
+
order = "(CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC, body"
|
|
74
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
75
|
+
post2 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
|
76
|
+
assert_equal post1, Post.order(order).first
|
|
77
|
+
assert_equal post2, Post.order(order).second
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'support primary: quoted table and column, secondary: case expresion' do
|
|
81
|
+
order = "[posts].[body] DESC, (CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC"
|
|
82
|
+
post1 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
|
83
|
+
post2 = Post.create title: 'ZZY Post', body: 'ZZZ Test cased orders.'
|
|
84
|
+
assert_equal post1, Post.order(order).first
|
|
85
|
+
assert_equal post2, Post.order(order).second
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'support inline function' do
|
|
89
|
+
order = "LEN(title)"
|
|
90
|
+
post1 = Post.create title: 'A', body: 'AAA Test cased orders.'
|
|
91
|
+
assert_equal post1, Post.order(order).first
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'support inline function with parameters' do
|
|
95
|
+
order = "SUBSTRING(title, 1, 3)"
|
|
96
|
+
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
|
97
|
+
assert_equal post1, Post.order(order).first
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'support inline function with parameters DESC' do
|
|
101
|
+
order = "SUBSTRING(title, 1, 3) DESC"
|
|
102
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
103
|
+
assert_equal post1, Post.order(order).first
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'support primary: inline function, secondary: column' do
|
|
107
|
+
order = "LEN(title), body"
|
|
108
|
+
post1 = Post.create title: 'A', body: 'AAA Test cased orders.'
|
|
109
|
+
post2 = Post.create title: 'A', body: 'Test cased orders.'
|
|
110
|
+
assert_equal post1, Post.order(order).first
|
|
111
|
+
assert_equal post2, Post.order(order).second
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'support primary: inline function, secondary: column with direction' do
|
|
115
|
+
order = "LEN(title) ASC, body DESC"
|
|
116
|
+
post1 = Post.create title: 'A', body: 'ZZZ Test cased orders.'
|
|
117
|
+
post2 = Post.create title: 'A', body: 'Test cased orders.'
|
|
118
|
+
assert_equal post1, Post.order(order).first
|
|
119
|
+
assert_equal post2, Post.order(order).second
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'support primary: column, secondary: inline function' do
|
|
123
|
+
order = "body DESC, LEN(title)"
|
|
124
|
+
post1 = Post.create title: 'Post', body: 'ZZZ Test cased orders.'
|
|
125
|
+
post2 = Post.create title: 'Longer Post', body: 'ZZZ Test cased orders.'
|
|
126
|
+
assert_equal post1, Post.order(order).first
|
|
127
|
+
assert_equal post2, Post.order(order).second
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'support primary: case expression, secondary: inline function' do
|
|
131
|
+
order = "CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC, LEN(body) ASC"
|
|
132
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Z'
|
|
133
|
+
post2 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
|
134
|
+
assert_equal post1, Post.order(order).first
|
|
135
|
+
assert_equal post2, Post.order(order).second
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'support primary: inline function, secondary: case expression' do
|
|
139
|
+
order = "LEN(body), CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC"
|
|
140
|
+
post1 = Post.create title: 'ZZZ Post', body: 'Z'
|
|
141
|
+
post2 = Post.create title: 'Post', body: 'Z'
|
|
142
|
+
assert_equal post1, Post.order(order).first
|
|
143
|
+
assert_equal post2, Post.order(order).second
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
end
|