tiny_tds 1.0.4 → 3.2.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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +20 -0
  3. data/.gitattributes +1 -0
  4. data/.github/workflows/ci.yml +590 -0
  5. data/.gitignore +2 -0
  6. data/.rubocop.yml +31 -0
  7. data/{CHANGELOG → CHANGELOG.md} +133 -26
  8. data/Gemfile +1 -5
  9. data/ISSUE_TEMPLATE.md +36 -3
  10. data/README.md +147 -85
  11. data/Rakefile +51 -94
  12. data/VERSION +1 -1
  13. data/docker-compose.yml +34 -0
  14. data/ext/tiny_tds/client.c +149 -67
  15. data/ext/tiny_tds/client.h +11 -5
  16. data/ext/tiny_tds/extconf.rb +144 -283
  17. data/ext/tiny_tds/extconsts.rb +4 -11
  18. data/ext/tiny_tds/result.c +68 -50
  19. data/ext/tiny_tds/tiny_tds_ext.c +4 -1
  20. data/lib/tiny_tds/bin.rb +44 -40
  21. data/lib/tiny_tds/client.rb +63 -55
  22. data/lib/tiny_tds/error.rb +0 -3
  23. data/lib/tiny_tds/gem.rb +23 -0
  24. data/lib/tiny_tds/result.rb +0 -3
  25. data/lib/tiny_tds.rb +37 -32
  26. data/{ports/patches/freetds/1.00 → patches/freetds/1.00.27}/0001-mingw_missing_inet_pton.diff +4 -4
  27. data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
  28. data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
  29. data/setup_cimgruby_dev.sh +25 -0
  30. data/start_dev.sh +21 -0
  31. data/tasks/native_gem.rake +16 -0
  32. data/tasks/package.rake +6 -0
  33. data/tasks/ports.rake +24 -0
  34. data/tasks/test.rake +7 -0
  35. data/test/bin/install-freetds.sh +18 -0
  36. data/test/bin/install-mssql.ps1 +42 -0
  37. data/test/bin/install-mssqltools.sh +9 -0
  38. data/test/bin/install-openssl.sh +18 -0
  39. data/test/bin/restore-from-native-gem.ps1 +10 -0
  40. data/test/bin/setup_tinytds_db.sh +7 -0
  41. data/test/bin/setup_volume_permissions.sh +10 -0
  42. data/test/client_test.rb +161 -112
  43. data/test/gem_test.rb +100 -0
  44. data/test/result_test.rb +293 -313
  45. data/test/schema_test.rb +369 -395
  46. data/test/sql/db-create.sql +18 -0
  47. data/test/sql/db-login.sql +38 -0
  48. data/test/test_helper.rb +116 -85
  49. data/test/thread_test.rb +22 -31
  50. data/tiny_tds.gemspec +27 -24
  51. metadata +109 -56
  52. data/appveyor.yml +0 -51
  53. data/test/appveyor/dbsetup.ps1 +0 -27
  54. data/test/appveyor/dbsetup.sql +0 -9
  55. data/test/benchmark/query.rb +0 -77
  56. data/test/benchmark/query_odbc.rb +0 -106
  57. data/test/benchmark/query_tinytds.rb +0 -126
  58. data/test/schema/sqlserver_2000.sql +0 -140
  59. data/test/schema/sqlserver_2005.sql +0 -140
  60. data/test/schema/sqlserver_2014.sql +0 -140
  61. data/test/schema/sybase_ase.sql +0 -138
  62. /data/bin/{defncopy → defncopy-ttds} +0 -0
  63. /data/bin/{tsql → tsql-ttds} +0 -0
  64. /data/test/schema/{sqlserver_2008.sql → sqlserver_2017.sql} +0 -0
data/test/result_test.rb CHANGED
@@ -1,43 +1,40 @@
1
- # encoding: utf-8
2
- require 'test_helper'
1
+ require "test_helper"
3
2
 
4
3
  class ResultTest < TinyTds::TestCase
5
-
6
- describe 'Basic query and result' do
7
-
4
+ describe "Basic query and result" do
8
5
  before do
9
6
  @@current_schema_loaded ||= load_current_schema
10
7
  @client = new_connection
11
- @query1 = 'SELECT 1 AS [one]'
8
+ @query1 = "SELECT 1 AS [one]"
12
9
  end
13
10
 
14
- it 'has included Enumerable' do
11
+ it "has included Enumerable" do
15
12
  assert TinyTds::Result.ancestors.include?(Enumerable)
16
13
  end
17
14
 
18
- it 'responds to #each' do
15
+ it "responds to #each" do
19
16
  result = @client.execute(@query1)
20
17
  assert result.respond_to?(:each)
21
18
  end
22
19
 
23
- it 'returns all results for #each with no block' do
20
+ it "returns all results for #each with no block" do
24
21
  result = @client.execute(@query1)
25
22
  data = result.each
26
23
  row = data.first
27
24
  assert_instance_of Array, data
28
25
  assert_equal 1, data.size
29
- assert_instance_of Hash, row, 'hash is the default query option'
26
+ assert_instance_of Hash, row, "hash is the default query option"
30
27
  end
31
28
 
32
- it 'returns all results for #each with a block yielding a row at a time' do
29
+ it "returns all results for #each with a block yielding a row at a time" do
33
30
  result = @client.execute(@query1)
34
31
  data = result.each do |row|
35
- assert_instance_of Hash, row, 'hash is the default query option'
32
+ assert_instance_of Hash, row, "hash is the default query option"
36
33
  end
37
34
  assert_instance_of Array, data
38
35
  end
39
36
 
40
- it 'allows successive calls to each returning the same data' do
37
+ it "allows successive calls to each returning the same data" do
41
38
  result = @client.execute(@query1)
42
39
  data = result.each
43
40
  result.each
@@ -45,151 +42,150 @@ class ResultTest < TinyTds::TestCase
45
42
  assert_equal data.first.object_id, result.each.first.object_id
46
43
  end
47
44
 
48
- it 'returns hashes with string keys' do
45
+ it "returns hashes with string keys" do
49
46
  result = @client.execute(@query1)
50
- row = result.each(:as => :hash, :symbolize_keys => false).first
47
+ row = result.each(as: :hash, symbolize_keys: false).first
51
48
  assert_instance_of Hash, row
52
- assert_equal ['one'], row.keys
53
- assert_equal ['one'], result.fields
49
+ assert_equal ["one"], row.keys
50
+ assert_equal ["one"], result.fields
54
51
  end
55
52
 
56
- it 'returns hashes with symbol keys' do
53
+ it "returns hashes with symbol keys" do
57
54
  result = @client.execute(@query1)
58
- row = result.each(:as => :hash, :symbolize_keys => true).first
55
+ row = result.each(as: :hash, symbolize_keys: true).first
59
56
  assert_instance_of Hash, row
60
57
  assert_equal [:one], row.keys
61
58
  assert_equal [:one], result.fields
62
59
  end
63
60
 
64
- it 'returns arrays with string fields' do
61
+ it "returns arrays with string fields" do
65
62
  result = @client.execute(@query1)
66
- row = result.each(:as => :array, :symbolize_keys => false).first
63
+ row = result.each(as: :array, symbolize_keys: false).first
67
64
  assert_instance_of Array, row
68
- assert_equal ['one'], result.fields
65
+ assert_equal ["one"], result.fields
69
66
  end
70
67
 
71
- it 'returns arrays with symbol fields' do
68
+ it "returns arrays with symbol fields" do
72
69
  result = @client.execute(@query1)
73
- row = result.each(:as => :array, :symbolize_keys => true).first
70
+ row = result.each(as: :array, symbolize_keys: true).first
74
71
  assert_instance_of Array, row
75
72
  assert_equal [:one], result.fields
76
73
  end
77
74
 
78
- it 'allows sql concat + to work' do
75
+ it "allows sql concat + to work" do
79
76
  rollback_transaction(@client) do
80
77
  @client.execute("DELETE FROM [datatypes]").do
81
78
  @client.execute("INSERT INTO [datatypes] ([char_10], [varchar_50]) VALUES ('1', '2')").do
82
- result = @client.execute("SELECT TOP (1) [char_10] + 'test' + [varchar_50] AS [test] FROM [datatypes]").each.first['test']
83
- result.must_equal "1 test2"
79
+ result = @client.execute("SELECT TOP (1) [char_10] + 'test' + [varchar_50] AS [test] FROM [datatypes]").each.first["test"]
80
+ _(result).must_equal "1 test2"
84
81
  end
85
82
  end
86
83
 
87
- it 'must be able to turn :cache_rows option off' do
84
+ it "must be able to turn :cache_rows option off" do
88
85
  result = @client.execute(@query1)
89
86
  local = []
90
- result.each(:cache_rows => false) do |row|
87
+ result.each(cache_rows: false) do |row|
91
88
  local << row
92
89
  end
93
- assert local.first, 'should have iterated over each row'
94
- assert_equal [], result.each, 'should not have been cached'
95
- assert_equal ['one'], result.fields, 'should still cache field names'
90
+ assert local.first, "should have iterated over each row"
91
+ assert_equal [], result.each, "should not have been cached"
92
+ assert_equal ["one"], result.fields, "should still cache field names"
96
93
  end
97
94
 
98
- it 'must be able to get the first result row only' do
95
+ it "must be able to get the first result row only" do
99
96
  load_current_schema
100
97
  big_query = "SELECT [id] FROM [datatypes]"
101
- one = @client.execute(big_query).each(:first => true)
98
+ one = @client.execute(big_query).each(first: true)
102
99
  many = @client.execute(big_query).each
103
100
  assert many.size > 1
104
101
  assert one.size == 1
105
102
  end
106
103
 
107
- it 'copes with no results when using first option' do
108
- data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(:first => true)
104
+ it "copes with no results when using first option" do
105
+ data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(first: true)
109
106
  assert_equal [], data
110
107
  end
111
108
 
112
- it 'must delete, insert and find data' do
109
+ it "must delete, insert and find data" do
113
110
  rollback_transaction(@client) do
114
- text = 'test insert and delete'
111
+ text = "test insert and delete"
115
112
  @client.execute("DELETE FROM [datatypes] WHERE [varchar_50] IS NOT NULL").do
116
113
  @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
117
114
  row = @client.execute("SELECT [varchar_50] FROM [datatypes] WHERE [varchar_50] IS NOT NULL").each.first
118
115
  assert row
119
- assert_equal text, row['varchar_50']
116
+ assert_equal text, row["varchar_50"]
120
117
  end
121
118
  end
122
119
 
123
- it 'must insert and find unicode data' do
120
+ it "must insert and find unicode data" do
124
121
  rollback_transaction(@client) do
125
- text = '😍'
122
+ text = "😍"
126
123
  @client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
127
124
  @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES (N'#{text}')").do
128
125
  row = @client.execute("SELECT [nvarchar_50] FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").each.first
129
- assert_equal text, row['nvarchar_50']
126
+ assert_equal text, row["nvarchar_50"]
130
127
  end
131
128
  end
132
129
 
133
- it 'must delete and update with affected rows support and insert with identity support in native sql' do
130
+ it "must delete and update with affected rows support and insert with identity support in native sql" do
134
131
  rollback_transaction(@client) do
135
- text = 'test affected rows sql'
132
+ text = "test affected rows sql"
136
133
  @client.execute("DELETE FROM [datatypes]").do
137
- afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
138
- assert_instance_of Fixnum, afrows
134
+ afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first["AffectedRows"]
135
+ _(["Fixnum", "Integer"]).must_include afrows.class.name
139
136
  @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
140
- pk1 = @client.execute(@client.identity_sql).each.first['Ident']
141
- assert_instance_of Fixnum, pk1, 'we it be able to CAST to bigint'
137
+ pk1 = @client.execute(@client.identity_sql).each.first["Ident"]
138
+ _(["Fixnum", "Integer"]).must_include pk1.class.name, "we it be able to CAST to bigint"
142
139
  @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
143
- afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
140
+ afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first["AffectedRows"]
144
141
  assert_equal 1, afrows
145
142
  end
146
143
  end
147
144
 
148
- it 'has a #do method that cancels result rows and returns affected rows natively' do
145
+ it "has a #do method that cancels result rows and returns affected rows natively" do
149
146
  rollback_transaction(@client) do
150
- text = 'test affected rows native'
151
- count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
147
+ text = "test affected rows native"
148
+ count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"]
152
149
  deleted_rows = @client.execute("DELETE FROM [datatypes]").do
153
- assert_equal count, deleted_rows, 'should have deleted rows equal to count'
150
+ assert_equal count, deleted_rows, "should have deleted rows equal to count"
154
151
  inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
155
- assert_equal 1, inserted_rows, 'should have inserted row for one above'
152
+ assert_equal 1, inserted_rows, "should have inserted row for one above"
156
153
  updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
157
- assert_equal 1, updated_rows, 'should have updated row for one above' unless sqlserver_2000? # Will report -1
154
+ assert_equal 1, updated_rows, "should have updated row for one above"
158
155
  end
159
156
  end
160
157
 
161
- it 'allows native affected rows using #do to work under transaction' do
158
+ it "allows native affected rows using #do to work under transaction" do
162
159
  rollback_transaction(@client) do
163
- text = 'test affected rows native in transaction'
160
+ text = "test affected rows native in transaction"
164
161
  @client.execute("BEGIN TRANSACTION").do
165
162
  @client.execute("DELETE FROM [datatypes]").do
166
163
  inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
167
- assert_equal 1, inserted_rows, 'should have inserted row for one above'
164
+ assert_equal 1, inserted_rows, "should have inserted row for one above"
168
165
  updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
169
- assert_equal 1, updated_rows, 'should have updated row for one above' unless sqlserver_2000? # Will report -1
166
+ assert_equal 1, updated_rows, "should have updated row for one above"
170
167
  end
171
168
  end
172
169
 
173
- it 'has an #insert method that cancels result rows and returns IDENTITY natively' do
170
+ it "has an #insert method that cancels result rows and returns IDENTITY natively" do
174
171
  rollback_transaction(@client) do
175
- text = 'test scope identity rows native'
172
+ text = "test scope identity rows native"
176
173
  @client.execute("DELETE FROM [datatypes] WHERE [varchar_50] = '#{text}'").do
177
174
  @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
178
- sql_identity = @client.execute(@client.identity_sql).each.first['Ident']
175
+ sql_identity = @client.execute(@client.identity_sql).each.first["Ident"]
179
176
  native_identity = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").insert
180
- assert_equal sql_identity+1, native_identity
177
+ assert_equal sql_identity + 1, native_identity
181
178
  end
182
179
  end
183
180
 
184
- it 'returns bigint for #insert when needed' do
181
+ it "returns bigint for #insert when needed" do
185
182
  return if sqlserver_azure? # We can not alter clustered index like this test does.
186
- return if sybase_ase? # On Sybase, sp_helpindex cannot be used inside a transaction since it does a
187
- # 'CREATE TABLE' command is not allowed within a multi-statement transaction
188
- # and and sp_helpindex creates a temporary table #spindtab.
183
+ # 'CREATE TABLE' command is not allowed within a multi-statement transaction
184
+ # and and sp_helpindex creates a temporary table #spindtab.
189
185
  rollback_transaction(@client) do
190
186
  seed = 9223372036854775805
191
187
  @client.execute("DELETE FROM [datatypes]").do
192
- id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect{ |row| row['index_keys'] == 'id' }['index_name']
188
+ id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect { |row| row["index_keys"] == "id" }["index_name"]
193
189
  @client.execute("ALTER TABLE [datatypes] DROP CONSTRAINT [#{id_constraint_name}]").do
194
190
  @client.execute("ALTER TABLE [datatypes] DROP COLUMN [id]").do
195
191
  @client.execute("ALTER TABLE [datatypes] ADD [id] [bigint] NOT NULL IDENTITY(1,1) PRIMARY KEY").do
@@ -199,146 +195,154 @@ class ResultTest < TinyTds::TestCase
199
195
  end
200
196
  end
201
197
 
202
- it 'must be able to begin/commit transactions with raw sql' do
198
+ it "must be able to begin/commit transactions with raw sql" do
203
199
  rollback_transaction(@client) do
204
200
  @client.execute("BEGIN TRANSACTION").do
205
201
  @client.execute("DELETE FROM [datatypes]").do
206
202
  @client.execute("COMMIT TRANSACTION").do
207
- count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
203
+ count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"]
208
204
  assert_equal 0, count
209
205
  end
210
206
  end
211
207
 
212
- it 'must be able to begin/rollback transactions with raw sql' do
208
+ it "must be able to begin/rollback transactions with raw sql" do
213
209
  load_current_schema
214
210
  @client.execute("BEGIN TRANSACTION").do
215
211
  @client.execute("DELETE FROM [datatypes]").do
216
212
  @client.execute("ROLLBACK TRANSACTION").do
217
- count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
218
- 0.wont_equal count
213
+ count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"]
214
+ _(count).wont_equal 0
219
215
  end
220
216
 
221
- it 'has a #fields accessor with logic default and valid outcome' do
217
+ it "has a #fields accessor with logic default and valid outcome" do
222
218
  result = @client.execute(@query1)
223
- result.fields.must_equal ['one']
219
+ _(result.fields).must_equal ["one"]
224
220
  result.each
225
- result.fields.must_equal ['one']
221
+ _(result.fields).must_equal ["one"]
226
222
  end
227
223
 
228
- it 'always returns an array for fields for all sql' do
224
+ it "always returns an array for fields for all sql" do
229
225
  result = @client.execute("USE [tinytdstest]")
230
- result.fields.must_equal []
226
+ _(result.fields).must_equal []
231
227
  result.do
232
- result.fields.must_equal []
228
+ _(result.fields).must_equal []
233
229
  end
234
230
 
235
- it 'returns fields even when no results are found' do
231
+ it "returns fields even when no results are found" do
236
232
  no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'"
237
233
  # Fields before each.
238
234
  result = @client.execute(no_results_query)
239
- result.fields.must_equal ['id','varchar_50']
235
+ _(result.fields).must_equal ["id", "varchar_50"]
240
236
  result.each
241
- result.fields.must_equal ['id','varchar_50']
237
+ _(result.fields).must_equal ["id", "varchar_50"]
242
238
  # Each then fields
243
239
  result = @client.execute(no_results_query)
244
240
  result.each
245
- result.fields.must_equal ['id','varchar_50']
241
+ _(result.fields).must_equal ["id", "varchar_50"]
246
242
  end
247
243
 
248
- it 'allows the result to be canceled before reading' do
244
+ it "allows the result to be canceled before reading" do
249
245
  result = @client.execute(@query1)
250
246
  result.cancel
251
247
  @client.execute(@query1).each
252
248
  end
253
249
 
254
- it 'works in tandem with the client when needing to find out if client has sql sent and result is canceled or not' do
250
+ it "works in tandem with the client when needing to find out if client has sql sent and result is canceled or not" do
255
251
  # Default state.
256
252
  @client = TinyTds::Client.new(connection_options)
257
- @client.sqlsent?.must_equal false
258
- @client.canceled?.must_equal false
253
+ _(@client.sqlsent?).must_equal false
254
+ _(@client.canceled?).must_equal false
259
255
  # With active result before and after cancel.
260
256
  result = @client.execute(@query1)
261
- @client.sqlsent?.must_equal true
262
- @client.canceled?.must_equal false
257
+ _(@client.sqlsent?).must_equal true
258
+ _(@client.canceled?).must_equal false
263
259
  result.cancel
264
- @client.sqlsent?.must_equal false
265
- @client.canceled?.must_equal true
266
- assert result.cancel, 'must be safe to call again'
260
+ _(@client.sqlsent?).must_equal false
261
+ _(@client.canceled?).must_equal true
262
+ assert result.cancel, "must be safe to call again"
267
263
  # With each and no block.
268
264
  @client.execute(@query1).each
269
- @client.sqlsent?.must_equal false
270
- @client.canceled?.must_equal false
265
+ _(@client.sqlsent?).must_equal false
266
+ _(@client.canceled?).must_equal false
271
267
  # With each and block.
272
268
  @client.execute(@query1).each do |row|
273
- @client.sqlsent?.must_equal true, 'when iterating over each row in a block'
274
- @client.canceled?.must_equal false
269
+ _(@client.sqlsent?).must_equal true, "when iterating over each row in a block"
270
+ _(@client.canceled?).must_equal false
275
271
  end
276
- @client.sqlsent?.must_equal false
277
- @client.canceled?.must_equal false
272
+ _(@client.sqlsent?).must_equal false
273
+ _(@client.canceled?).must_equal false
278
274
  # With each and block canceled half way thru.
279
- count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]['count']
280
- assert count > 10, 'since we want to cancel early for test'
275
+ count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]["count"]
276
+ assert count > 10, "since we want to cancel early for test"
281
277
  result = @client.execute("SELECT [id] FROM [datatypes]")
282
278
  index = 0
283
279
  result.each do |row|
284
280
  break if index > 10
285
281
  index += 1
286
282
  end
287
- @client.sqlsent?.must_equal true
288
- @client.canceled?.must_equal false
283
+ _(@client.sqlsent?).must_equal true
284
+ _(@client.canceled?).must_equal false
289
285
  result.cancel
290
- @client.sqlsent?.must_equal false
291
- @client.canceled?.must_equal true
286
+ _(@client.sqlsent?).must_equal false
287
+ _(@client.canceled?).must_equal true
292
288
  # With do method.
293
289
  @client.execute(@query1).do
294
- @client.sqlsent?.must_equal false
295
- @client.canceled?.must_equal true
290
+ _(@client.sqlsent?).must_equal false
291
+ _(@client.canceled?).must_equal true
296
292
  # With insert method.
297
293
  rollback_transaction(@client) do
298
294
  @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('test')").insert
299
- @client.sqlsent?.must_equal false
300
- @client.canceled?.must_equal true
295
+ _(@client.sqlsent?).must_equal false
296
+ _(@client.canceled?).must_equal true
301
297
  end
302
298
  # With first
303
- @client.execute("SELECT [id] FROM [datatypes]").each(:first => true)
304
- @client.sqlsent?.must_equal false
305
- @client.canceled?.must_equal true
299
+ @client.execute("SELECT [id] FROM [datatypes]").each(first: true)
300
+ _(@client.sqlsent?).must_equal false
301
+ _(@client.canceled?).must_equal true
306
302
  end
307
303
 
308
- it 'use same string object for hash keys' do
304
+ it "use same string object for hash keys" do
309
305
  data = @client.execute("SELECT [id], [bigint] FROM [datatypes]").each
310
- assert_equal data.first.keys.map{ |r| r.object_id }, data.last.keys.map{ |r| r.object_id }
306
+ assert_equal data.first.keys.map { |r| r.object_id }, data.last.keys.map { |r| r.object_id }
311
307
  end
312
308
 
313
- it 'has properly encoded column names with symbol keys' do
309
+ it "has properly encoded column names with symbol keys" do
314
310
  col_name = "öäüß"
315
- @client.execute("DROP TABLE [test_encoding]").do rescue nil
311
+ begin
312
+ @client.execute("DROP TABLE [test_encoding]").do
313
+ rescue
314
+ nil
315
+ end
316
316
  @client.execute("CREATE TABLE [dbo].[test_encoding] ( [id] int NOT NULL IDENTITY(1,1) PRIMARY KEY, [#{col_name}] [nvarchar](10) NOT NULL )").do
317
317
  @client.execute("INSERT INTO [test_encoding] ([#{col_name}]) VALUES (N'#{col_name}')").do
318
318
  result = @client.execute("SELECT [#{col_name}] FROM [test_encoding]")
319
- row = result.each(:as => :hash, :symbolize_keys => true).first
319
+ row = result.each(as: :hash, symbolize_keys: true).first
320
320
  assert_instance_of Symbol, result.fields.first
321
321
  assert_equal col_name.to_sym, result.fields.first
322
322
  assert_instance_of Symbol, row.keys.first
323
323
  assert_equal col_name.to_sym, row.keys.first
324
324
  end
325
325
 
326
- it 'allows #return_code to work with stored procedures and reset per sql batch' do
326
+ it "allows #return_code to work with stored procedures and reset per sql batch" do
327
327
  assert_nil @client.return_code
328
328
  result = @client.execute("EXEC tinytds_TestReturnCodes")
329
- assert_equal [{"one"=>1}], result.each
329
+ assert_equal [{"one" => 1}], result.each
330
330
  assert_equal 420, @client.return_code
331
331
  assert_equal 420, result.return_code
332
- result = @client.execute('SELECT 1 as [one]')
332
+ result = @client.execute("SELECT 1 as [one]")
333
333
  result.each
334
334
  assert_nil @client.return_code
335
335
  assert_nil result.return_code
336
336
  end
337
337
 
338
- describe 'with multiple result sets' do
338
+ it "with LOGINPROPERTY function" do
339
+ v = @client.execute("SELECT LOGINPROPERTY('sa', 'IsLocked') as v").first["v"]
340
+ _(v).must_equal 0
341
+ end
339
342
 
343
+ describe "with multiple result sets" do
340
344
  before do
341
- @empty_select = "SELECT 1 AS [rs1] WHERE 1 = 0"
345
+ @empty_select = "SELECT 1 AS [rs1] WHERE 1 = 0"
342
346
  @double_select = "SELECT 1 AS [rs1]
343
347
  SELECT 2 AS [rs2]"
344
348
  @triple_select_1st_empty = "SELECT 1 AS [rs1] WHERE 1 = 0
@@ -352,50 +356,41 @@ class ResultTest < TinyTds::TestCase
352
356
  SELECT 3 AS [rs3] WHERE 1 = 0"
353
357
  end
354
358
 
355
- it 'handles a command buffer with double selects' do
359
+ it "handles a command buffer with double selects" do
356
360
  result = @client.execute(@double_select)
357
361
  result_sets = result.each
358
362
  assert_equal 2, result_sets.size
359
- assert_equal [{'rs1' => 1}], result_sets.first
360
- assert_equal [{'rs2' => 2}], result_sets.last
361
- assert_equal [['rs1'], ['rs2']], result.fields
362
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
363
+ assert_equal [{"rs1" => 1}], result_sets.first
364
+ assert_equal [{"rs2" => 2}], result_sets.last
365
+ assert_equal [["rs1"], ["rs2"]], result.fields
366
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
363
367
  # As array
364
368
  result = @client.execute(@double_select)
365
- result_sets = result.each(:as => :array)
369
+ result_sets = result.each(as: :array)
366
370
  assert_equal 2, result_sets.size
367
371
  assert_equal [[1]], result_sets.first
368
372
  assert_equal [[2]], result_sets.last
369
- assert_equal [['rs1'], ['rs2']], result.fields
370
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
373
+ assert_equal [["rs1"], ["rs2"]], result.fields
374
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
371
375
  end
372
376
 
373
- it 'yields each row for each result set' do
377
+ it "yields each row for each result set" do
374
378
  data = []
375
379
  result_sets = @client.execute(@double_select).each { |row| data << row }
376
380
  assert_equal data.first, result_sets.first[0]
377
381
  assert_equal data.last, result_sets.last[0]
378
382
  end
379
383
 
380
- it 'works from a stored procedure' do
381
- if sqlserver?
382
- results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
383
- assert_equal [{"Object Name"=>"[datatypes]"}], results1
384
- constraint_info = results2.first
385
- assert constraint_info.key?("constraint_keys")
386
- assert constraint_info.key?("constraint_type")
387
- assert constraint_info.key?("constraint_name")
388
- elsif sybase_ase?
389
- results1, results2 = @client.execute("EXEC sp_helpconstraint 'datatypes'").each
390
- assert results1['name'] =~ /^datatypes_bit/
391
- assert results1['defintion'] == 'DEFAULT 0'
392
- assert results2['name'] =~ /^datatypes_id/
393
- assert results2['defintion'] =~ /^PRIMARY KEY/
394
- end
384
+ it "works from a stored procedure" do
385
+ results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
386
+ assert_equal [{"Object Name" => "[datatypes]"}], results1
387
+ constraint_info = results2.first
388
+ assert constraint_info.key?("constraint_keys")
389
+ assert constraint_info.key?("constraint_type")
390
+ assert constraint_info.key?("constraint_name")
395
391
  end
396
392
 
397
- describe 'using :empty_sets TRUE' do
398
-
393
+ describe "using :empty_sets TRUE" do
399
394
  before do
400
395
  close_client
401
396
  @old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
@@ -407,76 +402,74 @@ class ResultTest < TinyTds::TestCase
407
402
  TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value
408
403
  end
409
404
 
410
- it 'handles a basic empty result set' do
405
+ it "handles a basic empty result set" do
411
406
  result = @client.execute(@empty_select)
412
407
  assert_equal [], result.each
413
- assert_equal ['rs1'], result.fields
408
+ assert_equal ["rs1"], result.fields
414
409
  end
415
410
 
416
- it 'includes empty result sets by default - using 1st empty buffer' do
411
+ it "includes empty result sets by default - using 1st empty buffer" do
417
412
  result = @client.execute(@triple_select_1st_empty)
418
413
  result_sets = result.each
419
414
  assert_equal 3, result_sets.size
420
415
  assert_equal [], result_sets[0]
421
- assert_equal [{'rs2' => 2}], result_sets[1]
422
- assert_equal [{'rs3' => 3}], result_sets[2]
423
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
424
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
416
+ assert_equal [{"rs2" => 2}], result_sets[1]
417
+ assert_equal [{"rs3" => 3}], result_sets[2]
418
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
419
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
425
420
  # As array
426
421
  result = @client.execute(@triple_select_1st_empty)
427
- result_sets = result.each(:as => :array)
422
+ result_sets = result.each(as: :array)
428
423
  assert_equal 3, result_sets.size
429
424
  assert_equal [], result_sets[0]
430
425
  assert_equal [[2]], result_sets[1]
431
426
  assert_equal [[3]], result_sets[2]
432
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
433
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
427
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
428
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
434
429
  end
435
430
 
436
- it 'includes empty result sets by default - using 2nd empty buffer' do
431
+ it "includes empty result sets by default - using 2nd empty buffer" do
437
432
  result = @client.execute(@triple_select_2nd_empty)
438
433
  result_sets = result.each
439
434
  assert_equal 3, result_sets.size
440
- assert_equal [{'rs1' => 1}], result_sets[0]
435
+ assert_equal [{"rs1" => 1}], result_sets[0]
441
436
  assert_equal [], result_sets[1]
442
- assert_equal [{'rs3' => 3}], result_sets[2]
443
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
444
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
437
+ assert_equal [{"rs3" => 3}], result_sets[2]
438
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
439
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
445
440
  # As array
446
441
  result = @client.execute(@triple_select_2nd_empty)
447
- result_sets = result.each(:as => :array)
442
+ result_sets = result.each(as: :array)
448
443
  assert_equal 3, result_sets.size
449
444
  assert_equal [[1]], result_sets[0]
450
445
  assert_equal [], result_sets[1]
451
446
  assert_equal [[3]], result_sets[2]
452
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
453
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
447
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
448
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
454
449
  end
455
450
 
456
- it 'includes empty result sets by default - using 3rd empty buffer' do
451
+ it "includes empty result sets by default - using 3rd empty buffer" do
457
452
  result = @client.execute(@triple_select_3rd_empty)
458
453
  result_sets = result.each
459
454
  assert_equal 3, result_sets.size
460
- assert_equal [{'rs1' => 1}], result_sets[0]
461
- assert_equal [{'rs2' => 2}], result_sets[1]
455
+ assert_equal [{"rs1" => 1}], result_sets[0]
456
+ assert_equal [{"rs2" => 2}], result_sets[1]
462
457
  assert_equal [], result_sets[2]
463
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
464
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
458
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
459
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
465
460
  # As array
466
461
  result = @client.execute(@triple_select_3rd_empty)
467
- result_sets = result.each(:as => :array)
462
+ result_sets = result.each(as: :array)
468
463
  assert_equal 3, result_sets.size
469
464
  assert_equal [[1]], result_sets[0]
470
465
  assert_equal [[2]], result_sets[1]
471
466
  assert_equal [], result_sets[2]
472
- assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
473
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
467
+ assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields
468
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
474
469
  end
475
-
476
470
  end
477
471
 
478
- describe 'using :empty_sets FALSE' do
479
-
472
+ describe "using :empty_sets FALSE" do
480
473
  before do
481
474
  close_client
482
475
  @old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
@@ -488,231 +481,220 @@ class ResultTest < TinyTds::TestCase
488
481
  TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value
489
482
  end
490
483
 
491
- it 'handles a basic empty result set' do
484
+ it "handles a basic empty result set" do
492
485
  result = @client.execute(@empty_select)
493
486
  assert_equal [], result.each
494
- assert_equal ['rs1'], result.fields
487
+ assert_equal ["rs1"], result.fields
495
488
  end
496
489
 
497
- it 'must not include empty result sets by default - using 1st empty buffer' do
490
+ it "must not include empty result sets by default - using 1st empty buffer" do
498
491
  result = @client.execute(@triple_select_1st_empty)
499
492
  result_sets = result.each
500
493
  assert_equal 2, result_sets.size
501
- assert_equal [{'rs2' => 2}], result_sets[0]
502
- assert_equal [{'rs3' => 3}], result_sets[1]
503
- assert_equal [['rs2'], ['rs3']], result.fields
504
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
494
+ assert_equal [{"rs2" => 2}], result_sets[0]
495
+ assert_equal [{"rs3" => 3}], result_sets[1]
496
+ assert_equal [["rs2"], ["rs3"]], result.fields
497
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
505
498
  # As array
506
499
  result = @client.execute(@triple_select_1st_empty)
507
- result_sets = result.each(:as => :array)
500
+ result_sets = result.each(as: :array)
508
501
  assert_equal 2, result_sets.size
509
502
  assert_equal [[2]], result_sets[0]
510
503
  assert_equal [[3]], result_sets[1]
511
- assert_equal [['rs2'], ['rs3']], result.fields
512
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
504
+ assert_equal [["rs2"], ["rs3"]], result.fields
505
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
513
506
  end
514
507
 
515
- it 'must not include empty result sets by default - using 2nd empty buffer' do
508
+ it "must not include empty result sets by default - using 2nd empty buffer" do
516
509
  result = @client.execute(@triple_select_2nd_empty)
517
510
  result_sets = result.each
518
511
  assert_equal 2, result_sets.size
519
- assert_equal [{'rs1' => 1}], result_sets[0]
520
- assert_equal [{'rs3' => 3}], result_sets[1]
521
- assert_equal [['rs1'], ['rs3']], result.fields
522
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
512
+ assert_equal [{"rs1" => 1}], result_sets[0]
513
+ assert_equal [{"rs3" => 3}], result_sets[1]
514
+ assert_equal [["rs1"], ["rs3"]], result.fields
515
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
523
516
  # As array
524
517
  result = @client.execute(@triple_select_2nd_empty)
525
- result_sets = result.each(:as => :array)
518
+ result_sets = result.each(as: :array)
526
519
  assert_equal 2, result_sets.size
527
520
  assert_equal [[1]], result_sets[0]
528
521
  assert_equal [[3]], result_sets[1]
529
- assert_equal [['rs1'], ['rs3']], result.fields
530
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
522
+ assert_equal [["rs1"], ["rs3"]], result.fields
523
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
531
524
  end
532
525
 
533
- it 'must not include empty result sets by default - using 3rd empty buffer' do
526
+ it "must not include empty result sets by default - using 3rd empty buffer" do
534
527
  result = @client.execute(@triple_select_3rd_empty)
535
528
  result_sets = result.each
536
529
  assert_equal 2, result_sets.size
537
- assert_equal [{'rs1' => 1}], result_sets[0]
538
- assert_equal [{'rs2' => 2}], result_sets[1]
539
- assert_equal [['rs1'], ['rs2']], result.fields
540
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
530
+ assert_equal [{"rs1" => 1}], result_sets[0]
531
+ assert_equal [{"rs2" => 2}], result_sets[1]
532
+ assert_equal [["rs1"], ["rs2"]], result.fields
533
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
541
534
  # As array
542
535
  result = @client.execute(@triple_select_3rd_empty)
543
- result_sets = result.each(:as => :array)
536
+ result_sets = result.each(as: :array)
544
537
  assert_equal 2, result_sets.size
545
538
  assert_equal [[1]], result_sets[0]
546
539
  assert_equal [[2]], result_sets[1]
547
- assert_equal [['rs1'], ['rs2']], result.fields
548
- assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
540
+ assert_equal [["rs1"], ["rs2"]], result.fields
541
+ assert_equal result.each.object_id, result.each.object_id, "same cached rows"
549
542
  end
550
-
551
543
  end
552
-
553
544
  end
554
545
 
555
- describe 'Complex query with multiple results sets but no actual results' do
546
+ unless sqlserver_azure?
547
+ describe "Complex query with multiple results sets but no actual results" do
548
+ let(:backup_file) { 'C:\\Users\\Public\\tinytdstest.bak' }
556
549
 
557
- let(:backup_file) { 'C:\\Users\\Public\\tinytdstest.bak' }
550
+ after { File.delete(backup_file) if File.exist?(backup_file) }
558
551
 
559
- after { File.delete(backup_file) if File.exist?(backup_file) }
560
-
561
- it 'must not cancel the query until complete' do
562
- @client.execute("BACKUP DATABASE tinytdstest TO DISK = '#{backup_file}'").do
552
+ it "must not cancel the query until complete" do
553
+ @client.execute("BACKUP DATABASE tinytdstest TO DISK = '#{backup_file}'").do
554
+ end
563
555
  end
556
+ end
564
557
 
565
- end unless sqlserver_azure?
566
-
567
- describe 'when casting to native ruby values' do
568
-
569
- it 'returns fixnum for 1' do
570
- value = @client.execute('SELECT 1 AS [fixnum]').each.first['fixnum']
558
+ describe "when casting to native ruby values" do
559
+ it "returns fixnum for 1" do
560
+ value = @client.execute("SELECT 1 AS [fixnum]").each.first["fixnum"]
571
561
  assert_equal 1, value
572
562
  end
573
563
 
574
- it 'returns nil for NULL' do
575
- value = @client.execute('SELECT NULL AS [null]').each.first['null']
576
- assert_equal nil, value
564
+ it "returns nil for NULL" do
565
+ value = @client.execute("SELECT NULL AS [null]").each.first["null"]
566
+ assert_nil value
577
567
  end
578
-
579
568
  end
580
569
 
581
- describe 'with data type' do
582
-
583
- describe 'char max' do
584
-
570
+ describe "with data type" do
571
+ describe "char max" do
585
572
  before do
586
- @big_text = 'x' * 2_000_000
587
- @old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first['textsize'].inspect
588
- @client.execute("SET TEXTSIZE #{(@big_text.length*2)+1}").do
573
+ @big_text = "x" * 2_000_000
574
+ @old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first["textsize"].inspect
575
+ @client.execute("SET TEXTSIZE #{(@big_text.length * 2) + 1}").do
589
576
  end
590
577
 
591
- it 'must insert and select large varchar_max' do
578
+ it "must insert and select large varchar_max" do
592
579
  insert_and_select_datatype :varchar_max
593
580
  end
594
581
 
595
- it 'must insert and select large nvarchar_max' do
582
+ it "must insert and select large nvarchar_max" do
596
583
  insert_and_select_datatype :nvarchar_max
597
584
  end
598
-
599
- end unless sqlserver_2000? || sybase_ase?
600
-
585
+ end
601
586
  end
602
587
 
603
- describe 'when shit happens' do
604
-
605
- it 'copes with nil or empty buffer' do
588
+ describe "when shit happens" do
589
+ it "copes with nil or empty buffer" do
606
590
  assert_raises(TypeError) { @client.execute(nil) }
607
- assert_equal [], @client.execute('').each
591
+ assert_equal [], @client.execute("").each
608
592
  end
609
593
 
610
- if sqlserver?
594
+ describe "using :message_handler option" do
595
+ let(:messages) { [] }
611
596
 
612
- it 'must not raise an error when severity is 10 or less' do
613
- (1..10).to_a.each do |severity|
614
- @client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
615
- end
597
+ before do
598
+ close_client
599
+ @client = new_connection message_handler: proc { |m| messages << m }
616
600
  end
617
601
 
618
- it 'raises an error when severity is greater than 10' do
619
- action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
620
- assert_raise_tinytds_error(action) do |e|
621
- assert_equal "Test 11 severity", e.message
622
- assert_equal 11, e.severity
623
- assert_equal 50000, e.db_error_number
602
+ after do
603
+ messages.clear
604
+ end
605
+
606
+ it "has a message handler that responds to call" do
607
+ assert @client.message_handler.respond_to?(:call)
608
+ end
609
+
610
+ it "calls the provided message handler when severity is 10 or less" do
611
+ (1..10).to_a.each do |severity|
612
+ messages.clear
613
+ msg = "Test #{severity} severity"
614
+ state = rand(1..255)
615
+ @client.execute("RAISERROR(N'#{msg}', #{severity}, #{state})").do
616
+ m = messages.first
617
+ assert_equal 1, messages.length, "there should be one message after one raiserror"
618
+ assert_equal msg, m.message, "message text"
619
+ assert_equal severity, m.severity, "message severity" unless severity == 10 && m.severity.to_i == 0
620
+ assert_equal state, m.os_error_number, "message state"
624
621
  end
625
622
  end
626
623
 
627
- else
624
+ it "calls the provided message handler for `print` messages" do
625
+ messages.clear
626
+ msg = "hello"
627
+ @client.execute("PRINT '#{msg}'").do
628
+ m = messages.first
629
+ assert_equal 1, messages.length, "there should be one message after one print statement"
630
+ assert_equal msg, m.message, "message text"
631
+ end
628
632
 
629
- it 'raises an error' do
630
- action = lambda { @client.execute("RAISERROR 50000 N'Hello World'").do }
633
+ it "must raise an error preceded by a `print` message" do
634
+ messages.clear
635
+ action = lambda { @client.execute("EXEC tinytds_TestPrintWithError").do }
631
636
  assert_raise_tinytds_error(action) do |e|
632
- assert_equal "Hello World", e.message
633
- assert_equal 16, e.severity # predefined on ASE
637
+ assert_equal "hello", messages.first.message, "message text"
638
+
639
+ assert_equal "Error following print", e.message
640
+ assert_equal 16, e.severity
634
641
  assert_equal 50000, e.db_error_number
635
642
  end
636
- assert_followup_query
637
643
  end
638
644
 
639
- end
640
-
641
- it 'throws an error when you execute another query with other results pending' do
642
- result1 = @client.execute(@query1)
643
- action = lambda { @client.execute(@query1) }
644
- assert_raise_tinytds_error(action) do |e|
645
- assert_match %r|with results pending|i, e.message
646
- assert_equal 7, e.severity
647
- assert_equal 20019, e.db_error_number
645
+ it "calls the provided message handler for each of a series of `print` messages" do
646
+ messages.clear
647
+ @client.execute("EXEC tinytds_TestSeveralPrints").do
648
+ assert_equal ["hello 1", "hello 2", "hello 3"], messages.map { |e| e.message }, "message list"
648
649
  end
649
- end
650
650
 
651
- it 'must error gracefully with bad table name' do
652
- action = lambda { @client.execute('SELECT * FROM [foobar]').each }
653
- assert_raise_tinytds_error(action) do |e|
654
- pattern = sybase_ase? ? /foobar not found/ : %r|invalid object name.*foobar|i
655
- assert_match pattern, e.message
656
- assert_equal 16, e.severity
657
- assert_equal 208, e.db_error_number
651
+ it "should flush info messages before raising error in cases of timeout" do
652
+ @client = new_connection timeout: 1, message_handler: proc { |m| messages << m }
653
+ action = lambda { @client.execute("print 'hello'; waitfor delay '00:00:02'").do }
654
+ messages.clear
655
+ assert_raise_tinytds_error(action) do |e|
656
+ assert_match %r{timed out}i, e.message, "ignore if non-english test run"
657
+ assert_equal 6, e.severity
658
+ assert_equal 20003, e.db_error_number
659
+ assert_equal "hello", messages.first&.message, "message text"
660
+ end
658
661
  end
659
- assert_followup_query
660
- end
661
662
 
662
- it 'must error gracefully with incorrect syntax' do
663
- action = lambda { @client.execute('this will not work').each }
664
- assert_raise_tinytds_error(action) do |e|
665
- assert_match %r|incorrect syntax|i, e.message
666
- assert_equal 15, e.severity
667
- assert_equal 156, e.db_error_number
663
+ it "should print info messages before raising error in cases of timeout" do
664
+ @client = new_connection timeout: 1, message_handler: proc { |m| messages << m }
665
+ action = lambda { @client.execute("raiserror('hello', 1, 1) with nowait; waitfor delay '00:00:02'").do }
666
+ messages.clear
667
+ assert_raise_tinytds_error(action) do |e|
668
+ assert_match %r{timed out}i, e.message, "ignore if non-english test run"
669
+ assert_equal 6, e.severity
670
+ assert_equal 20003, e.db_error_number
671
+ assert_equal "hello", messages.first&.message, "message text"
672
+ end
668
673
  end
669
- assert_followup_query
670
674
  end
671
675
 
672
- it 'must not error at all from reading non-convertable charcters and just use ? marks' do
673
- close_client
674
- @client = new_connection :encoding => 'ASCII'
675
- @client.charset.must_equal 'ASCII'
676
- find_value(202, :nvarchar_50).must_equal 'test nvarchar_50 ??'
677
- end
678
-
679
- it 'must error gracefully from writing non-convertable characters' do
680
- close_client
681
- @client = new_connection :encoding => 'ASCII'
682
- @client.charset.must_equal 'ASCII'
683
- rollback_transaction(@client) do
684
- text = 'Test ✓'
685
- @client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
686
- action = lambda { @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES ('#{text}')").do }
687
- assert_raise_tinytds_error(action) do |e|
688
- e.message.must_match %r{Unclosed quotation mark}i
689
- e.severity.must_equal 15
690
- e.db_error_number.must_equal 105
691
- end
692
- assert_followup_query
676
+ it "must not raise an error when severity is 10 or less" do
677
+ (1..10).to_a.each do |severity|
678
+ @client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
693
679
  end
694
680
  end
695
681
 
696
- it 'errors gracefully with incorrect syntax in sp_executesql' do
697
- action = lambda { @client.execute("EXEC sp_executesql N'this will not work'").each }
682
+ it "raises an error when severity is greater than 10" do
683
+ action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
698
684
  assert_raise_tinytds_error(action) do |e|
699
- assert_match %r|incorrect syntax|i, e.message
700
- assert_equal 15, e.severity
701
- assert_equal 156, e.db_error_number
685
+ assert_equal "Test 11 severity", e.message
686
+ assert_equal 11, e.severity
687
+ assert_equal 50000, e.db_error_number
702
688
  end
703
- assert_followup_query
704
- end unless sybase_ase?
705
-
689
+ end
706
690
  end
707
-
708
691
  end
709
692
 
710
-
711
693
  protected
712
694
 
713
695
  def assert_followup_query
714
696
  result = @client.execute(@query1)
715
- assert_equal 1, result.each.first['one']
697
+ assert_equal 1, result.each.first["one"]
716
698
  end
717
699
 
718
700
  def insert_and_select_datatype(datatype)
@@ -723,6 +705,4 @@ class ResultTest < TinyTds::TestCase
723
705
  flunk "Large #{datatype} data with a length of #{@big_text.length} did not match found text with length of #{found_text.length}" unless @big_text == found_text
724
706
  end
725
707
  end
726
-
727
708
  end
728
-