activerecord-sqlserver-adapter 5.2.1 → 6.0.2
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 +4 -4
- data/.editorconfig +9 -0
- data/.github/issue_template.md +23 -0
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +58 -20
- data/{Dockerfile → Dockerfile.ci} +1 -1
- data/Gemfile +48 -41
- data/Guardfile +9 -8
- data/README.md +28 -31
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +14 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +25 -14
- data/appveyor.yml +24 -17
- data/docker-compose.ci.yml +7 -5
- data/guides/RELEASING.md +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +8 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +88 -44
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +9 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +46 -8
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -5
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +210 -163
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +43 -44
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +7 -9
- data/lib/active_record/connection_adapters/sqlserver/type.rb +38 -35
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +6 -6
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +8 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +145 -94
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -5
- data/lib/active_record/sqlserver_base.rb +9 -1
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +28 -32
- data/lib/activerecord-sqlserver-adapter.rb +3 -1
- data/lib/arel/visitors/sqlserver.rb +108 -34
- data/lib/arel_sqlserver.rb +4 -2
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +246 -171
- data/test/cases/change_column_null_test_sqlserver.rb +14 -12
- data/test/cases/coerced_tests.rb +722 -381
- data/test/cases/column_test_sqlserver.rb +287 -285
- data/test/cases/connection_test_sqlserver.rb +17 -20
- data/test/cases/execute_procedure_test_sqlserver.rb +20 -20
- data/test/cases/fetch_test_sqlserver.rb +16 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +15 -19
- data/test/cases/helper_sqlserver.rb +15 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +15 -15
- data/test/cases/json_test_sqlserver.rb +25 -25
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +67 -27
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/order_test_sqlserver.rb +53 -54
- data/test/cases/pessimistic_locking_test_sqlserver.rb +27 -33
- data/test/cases/rake_test_sqlserver.rb +33 -45
- data/test/cases/schema_dumper_test_sqlserver.rb +115 -109
- data/test/cases/schema_test_sqlserver.rb +20 -26
- data/test/cases/scratchpad_test_sqlserver.rb +4 -4
- data/test/cases/showplan_test_sqlserver.rb +28 -35
- data/test/cases/specific_schema_test_sqlserver.rb +68 -65
- data/test/cases/transaction_test_sqlserver.rb +18 -20
- data/test/cases/trigger_test_sqlserver.rb +14 -13
- data/test/cases/utils_test_sqlserver.rb +70 -70
- data/test/cases/uuid_test_sqlserver.rb +13 -14
- data/test/debug.rb +8 -6
- data/test/migrations/create_clients_and_change_column_null.rb +3 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +4 -4
- data/test/models/sqlserver/booking.rb +3 -1
- data/test/models/sqlserver/customers_view.rb +3 -1
- data/test/models/sqlserver/datatype.rb +2 -0
- data/test/models/sqlserver/datatype_migration.rb +2 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -1
- data/test/models/sqlserver/edge_schema.rb +3 -3
- data/test/models/sqlserver/fk_has_fk.rb +3 -1
- data/test/models/sqlserver/fk_has_pk.rb +3 -1
- data/test/models/sqlserver/natural_pk_data.rb +4 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -1
- data/test/models/sqlserver/no_pk_data.rb +3 -1
- data/test/models/sqlserver/object_default.rb +3 -1
- data/test/models/sqlserver/quoted_table.rb +4 -2
- data/test/models/sqlserver/quoted_view_1.rb +3 -1
- data/test/models/sqlserver/quoted_view_2.rb +3 -1
- data/test/models/sqlserver/sst_memory.rb +3 -1
- data/test/models/sqlserver/string_default.rb +3 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -1
- data/test/models/sqlserver/string_defaults_view.rb +3 -1
- data/test/models/sqlserver/tinyint_pk.rb +3 -1
- data/test/models/sqlserver/trigger.rb +4 -2
- data/test/models/sqlserver/trigger_history.rb +3 -1
- data/test/models/sqlserver/upper.rb +3 -1
- data/test/models/sqlserver/uppered.rb +3 -1
- data/test/models/sqlserver/uuid.rb +3 -1
- data/test/schema/sqlserver_specific_schema.rb +31 -21
- data/test/support/coerceable_test_sqlserver.rb +15 -9
- data/test/support/connection_reflection.rb +3 -2
- data/test/support/core_ext/query_cache.rb +4 -1
- data/test/support/load_schema_sqlserver.rb +5 -5
- data/test/support/minitest_sqlserver.rb +3 -1
- data/test/support/paths_sqlserver.rb +11 -11
- data/test/support/rake_helpers.rb +13 -10
- data/test/support/sql_counter_sqlserver.rb +3 -4
- data/test/support/test_in_memory_oltp.rb +9 -7
- metadata +27 -12
- data/.travis.yml +0 -25
data/lib/arel_sqlserver.rb
CHANGED
data/test/appveyor/dbsetup.ps1
CHANGED
|
@@ -5,15 +5,15 @@ Write-Output "Setting up..."
|
|
|
5
5
|
|
|
6
6
|
Write-Output "Setting variables..."
|
|
7
7
|
$serverName = $env:COMPUTERNAME
|
|
8
|
-
$
|
|
8
|
+
$instanceNames = @('SQL2014')
|
|
9
9
|
$smo = 'Microsoft.SqlServer.Management.Smo.'
|
|
10
10
|
$wmi = new-object ($smo + 'Wmi.ManagedComputer')
|
|
11
11
|
|
|
12
12
|
Write-Output "Configure Instances..."
|
|
13
|
-
foreach ($
|
|
14
|
-
Write-Output "Instance $
|
|
13
|
+
foreach ($instanceName in $instanceNames) {
|
|
14
|
+
Write-Output "Instance $instanceName ..."
|
|
15
15
|
Write-Output "Enable TCP/IP and port 1433..."
|
|
16
|
-
$uri = "ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$
|
|
16
|
+
$uri = "ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Tcp']"
|
|
17
17
|
$tcp = $wmi.GetSmoObject($uri)
|
|
18
18
|
$tcp.IsEnabled = $true
|
|
19
19
|
foreach ($ipAddress in $Tcp.IPAddresses) {
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
require 'models/topic'
|
|
3
|
-
require 'models/task'
|
|
4
|
-
require 'models/post'
|
|
5
|
-
require 'models/subscriber'
|
|
6
|
-
require 'models/minimalistic'
|
|
1
|
+
# frozen_string_literal: true
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
|
+
require "models/topic"
|
|
5
|
+
require "models/task"
|
|
6
|
+
require "models/post"
|
|
7
|
+
require "models/subscriber"
|
|
8
|
+
require "models/minimalistic"
|
|
9
|
+
require "models/college"
|
|
9
10
|
|
|
11
|
+
class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
10
12
|
fixtures :tasks
|
|
11
13
|
|
|
12
14
|
let(:basic_insert_sql) { "INSERT INTO [funny_jokes] ([name]) VALUES('Knock knock')" }
|
|
13
15
|
let(:basic_update_sql) { "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2" }
|
|
14
16
|
let(:basic_select_sql) { "SELECT * FROM [customers] WHERE ([customers].[id] = 1)" }
|
|
15
17
|
|
|
16
|
-
it
|
|
18
|
+
it "has basic and non-sensitive information in the adapters inspect method" do
|
|
17
19
|
string = connection.inspect
|
|
18
20
|
_(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
|
|
19
21
|
_(string).must_match %r{version\: \d.\d}
|
|
@@ -25,48 +27,97 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
25
27
|
_(string).wont_match %r{port}
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
it
|
|
30
|
+
it "has a 128 max #table_alias_length" do
|
|
29
31
|
assert connection.table_alias_length <= 128
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
it
|
|
34
|
+
it "raises invalid statement error for bad SQL" do
|
|
33
35
|
assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.update("UPDATE XXX") }
|
|
34
36
|
end
|
|
35
37
|
|
|
36
|
-
it
|
|
37
|
-
assert_equal
|
|
38
|
+
it "is has our adapter_name" do
|
|
39
|
+
assert_equal "SQLServer", connection.adapter_name
|
|
38
40
|
end
|
|
39
41
|
|
|
40
|
-
it
|
|
42
|
+
it "support DDL in transactions" do
|
|
41
43
|
assert connection.supports_ddl_transactions?
|
|
42
44
|
end
|
|
43
45
|
|
|
44
|
-
it
|
|
46
|
+
it "table exists works if table name prefixed by schema and owner" do
|
|
45
47
|
begin
|
|
46
|
-
assert_equal
|
|
48
|
+
assert_equal "topics", Topic.table_name
|
|
47
49
|
assert Topic.table_exists?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
# Test when owner included in table name.
|
|
52
|
+
Topic.table_name = "dbo.topics"
|
|
53
|
+
assert Topic.table_exists?, "Topics table name of 'dbo.topics' should return true for exists."
|
|
54
|
+
|
|
55
|
+
# Test when database and owner included in table name.
|
|
56
|
+
Topic.table_name = "#{ActiveRecord::Base.configurations["arunit"]['database']}.dbo.topics"
|
|
57
|
+
assert Topic.table_exists?, "Topics table name of '[DATABASE].dbo.topics' should return true for exists."
|
|
50
58
|
ensure
|
|
51
|
-
Topic.table_name =
|
|
59
|
+
Topic.table_name = "topics"
|
|
52
60
|
end
|
|
53
61
|
end
|
|
54
62
|
|
|
55
|
-
it
|
|
56
|
-
|
|
63
|
+
it "test table existence across database schemas" do
|
|
64
|
+
arunit_connection = Topic.connection
|
|
65
|
+
arunit2_connection = College.connection
|
|
66
|
+
|
|
67
|
+
arunit_database = arunit_connection.pool.spec.config[:database]
|
|
68
|
+
arunit2_database = arunit2_connection.pool.spec.config[:database]
|
|
69
|
+
|
|
70
|
+
# Assert that connections use different default databases schemas.
|
|
71
|
+
assert_not_equal arunit_database, arunit2_database
|
|
72
|
+
|
|
73
|
+
# Assert that the Topics table exists when using the Topics connection.
|
|
74
|
+
assert arunit_connection.table_exists?('topics'), 'Topics table exists using table name'
|
|
75
|
+
assert arunit_connection.table_exists?('dbo.topics'), 'Topics table exists using owner and table name'
|
|
76
|
+
assert arunit_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using database, owner and table name'
|
|
77
|
+
|
|
78
|
+
# Assert that the Colleges table exists when using the Colleges connection.
|
|
79
|
+
assert arunit2_connection.table_exists?('colleges'), 'College table exists using table name'
|
|
80
|
+
assert arunit2_connection.table_exists?('dbo.colleges'), 'College table exists using owner and table name'
|
|
81
|
+
assert arunit2_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'College table exists using database, owner and table name'
|
|
82
|
+
|
|
83
|
+
# Assert that the tables exist when using each others connection.
|
|
84
|
+
assert arunit_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'Colleges table exists using Topics connection'
|
|
85
|
+
assert arunit2_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using Colleges connection'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "return true to insert sql query for inserts only" do
|
|
89
|
+
assert connection.send(:insert_sql?, "INSERT...")
|
|
57
90
|
assert connection.send(:insert_sql?, "EXEC sp_executesql N'INSERT INTO [fk_test_has_fks] ([fk_id]) VALUES (@0); SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident', N'@0 int', @0 = 0")
|
|
58
|
-
assert !connection.send(:insert_sql?,
|
|
59
|
-
assert !connection.send(:insert_sql?,
|
|
91
|
+
assert !connection.send(:insert_sql?, "UPDATE...")
|
|
92
|
+
assert !connection.send(:insert_sql?, "SELECT...")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "return unquoted table name object from basic INSERT UPDATE and SELECT statements" do
|
|
96
|
+
assert_equal "funny_jokes", connection.send(:get_table_name, basic_insert_sql)
|
|
97
|
+
assert_equal "customers", connection.send(:get_table_name, basic_update_sql)
|
|
98
|
+
assert_equal "customers", connection.send(:get_table_name, basic_select_sql)
|
|
60
99
|
end
|
|
61
100
|
|
|
62
|
-
it
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
101
|
+
it "test bad connection" do
|
|
102
|
+
assert_raise ActiveRecord::NoDatabaseError do
|
|
103
|
+
config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
|
|
104
|
+
ActiveRecord::Base.sqlserver_connection config
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "test database exists returns false if database does not exist" do
|
|
109
|
+
config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
|
|
110
|
+
assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
|
|
111
|
+
"expected database to not exist"
|
|
66
112
|
end
|
|
67
113
|
|
|
68
|
-
|
|
114
|
+
it "test database exists returns true when the database exists" do
|
|
115
|
+
config = ActiveRecord::Base.configurations["arunit"]
|
|
116
|
+
assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
|
|
117
|
+
"expected database #{config[:database]} to exist"
|
|
118
|
+
end
|
|
69
119
|
|
|
120
|
+
describe "with different language" do
|
|
70
121
|
before do
|
|
71
122
|
@default_language = connection.user_options_language
|
|
72
123
|
end
|
|
@@ -76,18 +127,18 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
76
127
|
connection.send :initialize_dateformatter
|
|
77
128
|
end
|
|
78
129
|
|
|
79
|
-
it
|
|
130
|
+
it "memos users dateformat" do
|
|
80
131
|
connection.execute("SET LANGUAGE us_english") rescue nil
|
|
81
132
|
dateformat = connection.instance_variable_get(:@database_dateformat)
|
|
82
|
-
assert_equal
|
|
133
|
+
assert_equal "mdy", dateformat
|
|
83
134
|
end
|
|
84
135
|
|
|
85
|
-
it
|
|
136
|
+
it "has a dateformatter" do
|
|
86
137
|
assert Date::DATE_FORMATS[:_sqlserver_dateformat]
|
|
87
138
|
assert Time::DATE_FORMATS[:_sqlserver_dateformat]
|
|
88
139
|
end
|
|
89
140
|
|
|
90
|
-
it
|
|
141
|
+
it "does a datetime insertion when language is german" do
|
|
91
142
|
connection.execute("SET LANGUAGE deutsch")
|
|
92
143
|
connection.send :initialize_dateformatter
|
|
93
144
|
assert_nothing_raised do
|
|
@@ -96,40 +147,36 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
96
147
|
Task.create! starting: starting, ending: ending
|
|
97
148
|
end
|
|
98
149
|
end
|
|
99
|
-
|
|
100
150
|
end
|
|
101
151
|
|
|
102
|
-
describe
|
|
103
|
-
|
|
152
|
+
describe "testing #lowercase_schema_reflection" do
|
|
104
153
|
before do
|
|
105
154
|
SSTestUpper.delete_all
|
|
106
|
-
SSTestUpper.create COLUMN1:
|
|
107
|
-
SSTestUpper.create COLUMN1:
|
|
155
|
+
SSTestUpper.create COLUMN1: "Got a minute?", COLUMN2: 419
|
|
156
|
+
SSTestUpper.create COLUMN1: "Favorite number?", COLUMN2: 69
|
|
108
157
|
end
|
|
109
158
|
|
|
110
159
|
after do
|
|
111
160
|
connection.lowercase_schema_reflection = false
|
|
112
161
|
end
|
|
113
162
|
|
|
114
|
-
it
|
|
115
|
-
assert SSTestUpper.columns_hash[
|
|
116
|
-
assert_equal
|
|
117
|
-
assert_equal
|
|
118
|
-
assert SSTestUpper.columns_hash[
|
|
163
|
+
it "not lowercase schema reflection by default" do
|
|
164
|
+
assert SSTestUpper.columns_hash["COLUMN1"]
|
|
165
|
+
assert_equal "Got a minute?", SSTestUpper.first.COLUMN1
|
|
166
|
+
assert_equal "Favorite number?", SSTestUpper.last.COLUMN1
|
|
167
|
+
assert SSTestUpper.columns_hash["COLUMN2"]
|
|
119
168
|
end
|
|
120
169
|
|
|
121
|
-
it
|
|
170
|
+
it "lowercase schema reflection when set" do
|
|
122
171
|
connection.lowercase_schema_reflection = true
|
|
123
|
-
assert SSTestUppered.columns_hash[
|
|
124
|
-
assert_equal
|
|
125
|
-
assert_equal
|
|
126
|
-
assert SSTestUppered.columns_hash[
|
|
172
|
+
assert SSTestUppered.columns_hash["column1"]
|
|
173
|
+
assert_equal "Got a minute?", SSTestUppered.first.column1
|
|
174
|
+
assert_equal "Favorite number?", SSTestUppered.last.column1
|
|
175
|
+
assert SSTestUppered.columns_hash["column2"]
|
|
127
176
|
end
|
|
128
|
-
|
|
129
177
|
end
|
|
130
178
|
|
|
131
|
-
describe
|
|
132
|
-
|
|
179
|
+
describe "identity inserts" do
|
|
133
180
|
before do
|
|
134
181
|
@identity_insert_sql = "INSERT INTO [funny_jokes] ([id],[name]) VALUES(420,'Knock knock')"
|
|
135
182
|
@identity_insert_sql_unquoted = "INSERT INTO funny_jokes (id, name) VALUES(420, 'Knock knock')"
|
|
@@ -139,62 +186,60 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
139
186
|
@identity_insert_sql_unordered_sp = "EXEC sp_executesql N'INSERT INTO [funny_jokes] ([name],[id]) VALUES (@0, @1)', N'@0 nvarchar(255), @1 int', @0 = N'Knock knock', @1 = 420"
|
|
140
187
|
end
|
|
141
188
|
|
|
142
|
-
it
|
|
143
|
-
assert_equal
|
|
144
|
-
assert_equal
|
|
145
|
-
assert_equal
|
|
146
|
-
assert_equal
|
|
147
|
-
assert_equal
|
|
148
|
-
assert_equal
|
|
189
|
+
it "return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column" do
|
|
190
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql)
|
|
191
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unquoted)
|
|
192
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unordered)
|
|
193
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_sp)
|
|
194
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unquoted_sp)
|
|
195
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unordered_sp)
|
|
149
196
|
end
|
|
150
197
|
|
|
151
|
-
it
|
|
198
|
+
it "return false to #query_requires_identity_insert? for normal SQL" do
|
|
152
199
|
[basic_insert_sql, basic_update_sql, basic_select_sql].each do |sql|
|
|
153
|
-
assert !connection.send(:query_requires_identity_insert?,sql), "SQL was #{sql}"
|
|
200
|
+
assert !connection.send(:query_requires_identity_insert?, sql), "SQL was #{sql}"
|
|
154
201
|
end
|
|
155
202
|
end
|
|
156
203
|
|
|
157
|
-
it
|
|
158
|
-
task_id_column = Task.columns_hash[
|
|
204
|
+
it "find identity column using #identity_columns" do
|
|
205
|
+
task_id_column = Task.columns_hash["id"]
|
|
159
206
|
assert_equal task_id_column.name, connection.send(:identity_columns, Task.table_name).first.name
|
|
160
207
|
assert_equal task_id_column.sql_type, connection.send(:identity_columns, Task.table_name).first.sql_type
|
|
161
208
|
end
|
|
162
209
|
|
|
163
|
-
it
|
|
210
|
+
it "return an empty array when calling #identity_columns for a table_name with no identity" do
|
|
164
211
|
_(connection.send(:identity_columns, Subscriber.table_name)).must_equal []
|
|
165
212
|
end
|
|
166
|
-
|
|
167
213
|
end
|
|
168
214
|
|
|
169
|
-
describe
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
assert_equal '1', connection.quoted_true
|
|
215
|
+
describe "quoting" do
|
|
216
|
+
it "return 1 for #quoted_true" do
|
|
217
|
+
assert_equal "1", connection.quoted_true
|
|
173
218
|
end
|
|
174
219
|
|
|
175
|
-
it
|
|
176
|
-
assert_equal
|
|
220
|
+
it "return 0 for #quoted_false" do
|
|
221
|
+
assert_equal "0", connection.quoted_false
|
|
177
222
|
end
|
|
178
223
|
|
|
179
|
-
it
|
|
224
|
+
it "not escape backslash characters like abstract adapter" do
|
|
180
225
|
string_with_backslashs = "\\n"
|
|
181
226
|
assert_equal string_with_backslashs, connection.quote_string(string_with_backslashs)
|
|
182
227
|
end
|
|
183
228
|
|
|
184
|
-
it
|
|
185
|
-
assert_equal
|
|
186
|
-
assert_equal
|
|
187
|
-
assert_equal
|
|
229
|
+
it "quote column names with brackets" do
|
|
230
|
+
assert_equal "[foo]", connection.quote_column_name(:foo)
|
|
231
|
+
assert_equal "[foo]", connection.quote_column_name("foo")
|
|
232
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("foo.bar")
|
|
188
233
|
end
|
|
189
234
|
|
|
190
|
-
it
|
|
191
|
-
assert_equal
|
|
192
|
-
assert_equal
|
|
235
|
+
it "not quote already quoted column names with brackets" do
|
|
236
|
+
assert_equal "[foo]", connection.quote_column_name("[foo]")
|
|
237
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("[foo].[bar]")
|
|
193
238
|
end
|
|
194
239
|
|
|
195
|
-
it
|
|
196
|
-
assert_equal
|
|
197
|
-
assert_equal
|
|
240
|
+
it "quote table names like columns" do
|
|
241
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("foo.bar")
|
|
242
|
+
assert_equal "[foo].[bar].[baz]", connection.quote_column_name("foo.bar.baz")
|
|
198
243
|
end
|
|
199
244
|
|
|
200
245
|
it "surround string with national prefix" do
|
|
@@ -204,44 +249,40 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
204
249
|
it "escape all single quotes by repeating them" do
|
|
205
250
|
assert_equal "N'''quotation''s'''", connection.quote("'quotation's'")
|
|
206
251
|
end
|
|
207
|
-
|
|
208
252
|
end
|
|
209
253
|
|
|
210
|
-
describe
|
|
211
|
-
|
|
254
|
+
describe "disabling referential integrity" do
|
|
212
255
|
before do
|
|
213
256
|
connection.disable_referential_integrity { SSTestHasPk.delete_all; SSTestHasFk.delete_all }
|
|
214
257
|
@parent = SSTestHasPk.create!
|
|
215
258
|
@member = SSTestHasFk.create!(fk_id: @parent.id)
|
|
216
259
|
end
|
|
217
260
|
|
|
218
|
-
it
|
|
219
|
-
SSTestHasPk.connection.disable_referential_integrity {
|
|
261
|
+
it "NOT ALLOW by default the deletion of a referenced parent" do
|
|
262
|
+
SSTestHasPk.connection.disable_referential_integrity {}
|
|
220
263
|
assert_raise(ActiveRecord::StatementInvalid) { @parent.destroy }
|
|
221
264
|
end
|
|
222
265
|
|
|
223
|
-
it
|
|
266
|
+
it "ALLOW deletion of referenced parent using #disable_referential_integrity block" do
|
|
224
267
|
SSTestHasPk.connection.disable_referential_integrity { @parent.destroy }
|
|
225
268
|
end
|
|
226
269
|
|
|
227
|
-
it
|
|
270
|
+
it "again NOT ALLOW deletion of referenced parent after #disable_referential_integrity block" do
|
|
228
271
|
assert_raise(ActiveRecord::StatementInvalid) do
|
|
229
|
-
SSTestHasPk.connection.disable_referential_integrity {
|
|
272
|
+
SSTestHasPk.connection.disable_referential_integrity {}
|
|
230
273
|
@parent.destroy
|
|
231
274
|
end
|
|
232
275
|
end
|
|
233
276
|
|
|
234
|
-
it
|
|
277
|
+
it "not disable referential integrity for the same table twice" do
|
|
235
278
|
tables = SSTestHasPk.connection.tables_with_referential_integrity
|
|
236
279
|
assert_equal tables.size, tables.uniq.size
|
|
237
280
|
end
|
|
238
|
-
|
|
239
281
|
end
|
|
240
282
|
|
|
241
|
-
describe
|
|
242
|
-
|
|
283
|
+
describe "database statements" do
|
|
243
284
|
it "run the database consistency checker useroptions command" do
|
|
244
|
-
skip
|
|
285
|
+
skip "on azure" if connection_sqlserver_azure?
|
|
245
286
|
keys = [:textsize, :language, :isolation_level, :dateformat]
|
|
246
287
|
user_options = connection.user_options
|
|
247
288
|
keys.each do |key|
|
|
@@ -251,183 +292,217 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
251
292
|
end
|
|
252
293
|
|
|
253
294
|
it "return a underscored key hash with indifferent access of the results" do
|
|
254
|
-
skip
|
|
295
|
+
skip "on azure" if connection_sqlserver_azure?
|
|
255
296
|
user_options = connection.user_options
|
|
256
|
-
assert_equal
|
|
257
|
-
assert_equal
|
|
297
|
+
assert_equal "read committed", user_options["isolation_level"]
|
|
298
|
+
assert_equal "read committed", user_options[:isolation_level]
|
|
258
299
|
end
|
|
259
|
-
|
|
260
300
|
end
|
|
261
301
|
|
|
262
|
-
describe
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
assert_equal 'integer', connection.type_to_sql(:integer)
|
|
302
|
+
describe "schema statements" do
|
|
303
|
+
it "create integers when no limit supplied" do
|
|
304
|
+
assert_equal "integer", connection.type_to_sql(:integer)
|
|
266
305
|
end
|
|
267
306
|
|
|
268
|
-
it
|
|
269
|
-
assert_equal
|
|
307
|
+
it "create integers when limit is 4" do
|
|
308
|
+
assert_equal "integer", connection.type_to_sql(:integer, limit: 4)
|
|
270
309
|
end
|
|
271
310
|
|
|
272
|
-
it
|
|
273
|
-
assert_equal
|
|
311
|
+
it "create integers when limit is 3" do
|
|
312
|
+
assert_equal "integer", connection.type_to_sql(:integer, limit: 3)
|
|
274
313
|
end
|
|
275
314
|
|
|
276
|
-
it
|
|
277
|
-
assert_equal
|
|
315
|
+
it "create smallints when limit is 2" do
|
|
316
|
+
assert_equal "smallint", connection.type_to_sql(:integer, limit: 2)
|
|
278
317
|
end
|
|
279
318
|
|
|
280
|
-
it
|
|
281
|
-
assert_equal
|
|
319
|
+
it "create tinyints when limit is 1" do
|
|
320
|
+
assert_equal "tinyint", connection.type_to_sql(:integer, limit: 1)
|
|
282
321
|
end
|
|
283
322
|
|
|
284
|
-
it
|
|
285
|
-
assert_equal
|
|
286
|
-
assert_equal
|
|
287
|
-
assert_equal
|
|
288
|
-
assert_equal
|
|
323
|
+
it "create bigints when limit is greateer than 4" do
|
|
324
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 5)
|
|
325
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 6)
|
|
326
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 7)
|
|
327
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 8)
|
|
289
328
|
end
|
|
290
329
|
|
|
291
|
-
it
|
|
292
|
-
assert_equal
|
|
330
|
+
it "create floats when no limit supplied" do
|
|
331
|
+
assert_equal "float", connection.type_to_sql(:float)
|
|
293
332
|
end
|
|
294
|
-
|
|
295
333
|
end
|
|
296
334
|
|
|
297
|
-
describe
|
|
298
|
-
|
|
335
|
+
describe "views" do
|
|
299
336
|
# Using connection.views
|
|
300
337
|
|
|
301
|
-
it
|
|
338
|
+
it "return an array" do
|
|
302
339
|
assert_instance_of Array, connection.views
|
|
303
340
|
end
|
|
304
341
|
|
|
305
|
-
it
|
|
306
|
-
_(connection.views).must_include
|
|
342
|
+
it "find SSTestCustomersView table name" do
|
|
343
|
+
_(connection.views).must_include "sst_customers_view"
|
|
307
344
|
end
|
|
308
345
|
|
|
309
|
-
it
|
|
310
|
-
name =
|
|
346
|
+
it "work with dynamic finders" do
|
|
347
|
+
name = "MetaSkills"
|
|
311
348
|
customer = SSTestCustomersView.create! name: name
|
|
312
349
|
assert_equal customer, SSTestCustomersView.find_by_name(name)
|
|
313
350
|
end
|
|
314
351
|
|
|
315
|
-
it
|
|
316
|
-
systables = [
|
|
352
|
+
it "not contain system views" do
|
|
353
|
+
systables = ["sysconstraints", "syssegments"]
|
|
317
354
|
systables.each do |systable|
|
|
318
355
|
assert !connection.views.include?(systable), "This systable #{systable} should not be in the views array."
|
|
319
356
|
end
|
|
320
357
|
end
|
|
321
358
|
|
|
322
|
-
it
|
|
323
|
-
view_info = connection.send(:view_information,
|
|
324
|
-
assert_equal(
|
|
325
|
-
assert_match(/CREATE VIEW sst_customers_view/, view_info[
|
|
359
|
+
it "allow the connection#view_information method to return meta data on the view" do
|
|
360
|
+
view_info = connection.send(:view_information, "sst_customers_view")
|
|
361
|
+
assert_equal("sst_customers_view", view_info["TABLE_NAME"])
|
|
362
|
+
assert_match(/CREATE VIEW sst_customers_view/, view_info["VIEW_DEFINITION"])
|
|
326
363
|
end
|
|
327
364
|
|
|
328
|
-
it
|
|
329
|
-
assert_equal
|
|
330
|
-
assert_equal
|
|
365
|
+
it "allow the connection#view_table_name method to return true table_name for the view" do
|
|
366
|
+
assert_equal "customers", connection.send(:view_table_name, "sst_customers_view")
|
|
367
|
+
assert_equal "topics", connection.send(:view_table_name, "topics"), "No view here, the same table name should come back."
|
|
331
368
|
end
|
|
332
369
|
|
|
333
370
|
# With same column names
|
|
334
371
|
|
|
335
|
-
it
|
|
336
|
-
columns = [
|
|
372
|
+
it "have matching column objects" do
|
|
373
|
+
columns = ["id", "name", "balance"]
|
|
337
374
|
assert !SSTestCustomersView.columns.blank?
|
|
338
375
|
assert_equal columns.size, SSTestCustomersView.columns.size
|
|
339
376
|
columns.each do |colname|
|
|
340
377
|
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
|
|
341
|
-
|
|
342
|
-
|
|
378
|
+
SSTestCustomersView.columns_hash[colname],
|
|
379
|
+
"Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
|
|
343
380
|
end
|
|
344
381
|
end
|
|
345
382
|
|
|
346
|
-
it
|
|
347
|
-
_(SSTestCustomersView.primary_key).must_equal
|
|
348
|
-
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal
|
|
349
|
-
_(SSTestCustomersView.columns_hash[
|
|
383
|
+
it "find identity column" do
|
|
384
|
+
_(SSTestCustomersView.primary_key).must_equal "id"
|
|
385
|
+
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal "id"
|
|
386
|
+
_(SSTestCustomersView.columns_hash["id"]).must_be :is_identity?
|
|
350
387
|
end
|
|
351
388
|
|
|
352
|
-
it
|
|
389
|
+
it "find default values" do
|
|
353
390
|
assert_equal 0, SSTestCustomersView.new.balance
|
|
354
391
|
end
|
|
355
392
|
|
|
356
|
-
it
|
|
393
|
+
it "respond true to data_source_exists?" do
|
|
357
394
|
assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
|
|
358
395
|
end
|
|
359
396
|
|
|
360
397
|
# With aliased column names
|
|
361
398
|
|
|
362
|
-
it
|
|
363
|
-
columns = [
|
|
399
|
+
it "have matching column objects" do
|
|
400
|
+
columns = ["id", "pretend_null"]
|
|
364
401
|
assert !SSTestStringDefaultsView.columns.blank?
|
|
365
402
|
assert_equal columns.size, SSTestStringDefaultsView.columns.size
|
|
366
403
|
columns.each do |colname|
|
|
367
404
|
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
|
|
368
|
-
|
|
369
|
-
|
|
405
|
+
SSTestStringDefaultsView.columns_hash[colname],
|
|
406
|
+
"Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
|
|
370
407
|
end
|
|
371
408
|
end
|
|
372
409
|
|
|
373
|
-
it
|
|
374
|
-
_(SSTestStringDefaultsView.primary_key).must_equal
|
|
375
|
-
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal
|
|
376
|
-
_(SSTestStringDefaultsView.columns_hash[
|
|
410
|
+
it "find identity column" do
|
|
411
|
+
_(SSTestStringDefaultsView.primary_key).must_equal "id"
|
|
412
|
+
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal "id"
|
|
413
|
+
_(SSTestStringDefaultsView.columns_hash["id"]).must_be :is_identity?
|
|
377
414
|
end
|
|
378
415
|
|
|
379
|
-
it
|
|
380
|
-
assert_equal
|
|
381
|
-
|
|
416
|
+
it "find default values" do
|
|
417
|
+
assert_equal "null", SSTestStringDefaultsView.new.pretend_null,
|
|
418
|
+
SSTestStringDefaultsView.columns_hash["pretend_null"].inspect
|
|
382
419
|
end
|
|
383
420
|
|
|
384
|
-
it
|
|
421
|
+
it "respond true to data_source_exists?" do
|
|
385
422
|
assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
|
|
386
423
|
end
|
|
387
424
|
|
|
388
425
|
# That have more than 4000 chars for their defintion
|
|
389
426
|
|
|
390
|
-
it
|
|
427
|
+
it "cope with null returned for the defintion" do
|
|
391
428
|
assert_nothing_raised() { SSTestStringDefaultsBigView.columns }
|
|
392
429
|
end
|
|
393
430
|
|
|
394
|
-
it
|
|
395
|
-
assert_equal
|
|
396
|
-
|
|
431
|
+
it "using alternate view defintion still be able to find real default" do
|
|
432
|
+
assert_equal "null", SSTestStringDefaultsBigView.new.pretend_null,
|
|
433
|
+
SSTestStringDefaultsBigView.columns_hash["pretend_null"].inspect
|
|
397
434
|
end
|
|
398
|
-
|
|
399
435
|
end
|
|
400
436
|
|
|
401
|
-
describe
|
|
402
|
-
|
|
437
|
+
describe "database_prefix_remote_server?" do
|
|
403
438
|
after do
|
|
404
439
|
connection_options.delete(:database_prefix)
|
|
405
440
|
end
|
|
406
441
|
|
|
407
|
-
it
|
|
442
|
+
it "returns false if database_prefix is not configured" do
|
|
408
443
|
assert_equal false, connection.database_prefix_remote_server?
|
|
409
444
|
end
|
|
410
445
|
|
|
411
|
-
it
|
|
446
|
+
it "returns true if database_prefix has been set" do
|
|
412
447
|
connection_options[:database_prefix] = "server.database.schema."
|
|
413
448
|
assert_equal true, connection.database_prefix_remote_server?
|
|
414
449
|
end
|
|
415
450
|
|
|
416
|
-
it
|
|
451
|
+
it "returns false if database_prefix has been set incorrectly" do
|
|
417
452
|
connection_options[:database_prefix] = "server.database.schema"
|
|
418
453
|
assert_equal false, connection.database_prefix_remote_server?
|
|
419
454
|
end
|
|
420
|
-
|
|
421
455
|
end
|
|
422
456
|
|
|
423
|
-
it
|
|
424
|
-
if ENV[
|
|
425
|
-
_(SSTMemory.primary_key).must_equal
|
|
426
|
-
_(SSTMemory.columns_hash[
|
|
457
|
+
it "in_memory_oltp" do
|
|
458
|
+
if ENV["IN_MEMORY_OLTP"] && connection.supports_in_memory_oltp?
|
|
459
|
+
_(SSTMemory.primary_key).must_equal "id"
|
|
460
|
+
_(SSTMemory.columns_hash["id"]).must_be :is_identity?
|
|
427
461
|
else
|
|
428
|
-
skip
|
|
462
|
+
skip "supports_in_memory_oltp? => false"
|
|
429
463
|
end
|
|
430
464
|
end
|
|
431
465
|
|
|
432
|
-
|
|
466
|
+
describe "block writes to a database" do
|
|
467
|
+
def setup
|
|
468
|
+
@conn = ActiveRecord::Base.connection
|
|
469
|
+
@connection_handler = ActiveRecord::Base.connection_handler
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
473
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
474
|
+
@connection_handler.while_preventing_writes do
|
|
475
|
+
@conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|
|
433
479
|
|
|
480
|
+
def test_errors_when_an_update_query_is_called_while_preventing_writes
|
|
481
|
+
@conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
482
|
+
|
|
483
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
484
|
+
@connection_handler.while_preventing_writes do
|
|
485
|
+
@conn.update("UPDATE [subscribers] SET [subscribers].[name] = 'Aidan' WHERE [subscribers].[nick] = 'aido'")
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
def test_errors_when_a_delete_query_is_called_while_preventing_writes
|
|
491
|
+
@conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
492
|
+
|
|
493
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
494
|
+
@connection_handler.while_preventing_writes do
|
|
495
|
+
@conn.execute("DELETE FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes
|
|
501
|
+
@conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
502
|
+
|
|
503
|
+
@connection_handler.while_preventing_writes do
|
|
504
|
+
assert_equal 1, @conn.execute("SELECT * FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
end
|