tiny_tds 2.1.2 → 3.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 +5 -5
- data/.github/workflows/ci.yml +470 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +39 -1
- data/Gemfile +0 -7
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +50 -59
- data/Rakefile +15 -10
- data/VERSION +1 -1
- data/docker-compose.yml +34 -0
- data/ext/tiny_tds/client.c +100 -59
- data/ext/tiny_tds/client.h +5 -3
- data/ext/tiny_tds/extconf.rb +38 -16
- data/ext/tiny_tds/extconsts.rb +4 -10
- data/ext/tiny_tds/result.c +52 -45
- data/ext/tiny_tds/tiny_tds_ext.c +4 -1
- data/lib/tiny_tds/gem.rb +1 -6
- data/setup_cimgruby_dev.sh +25 -0
- data/start_dev.sh +21 -0
- data/tasks/native_gem.rake +15 -6
- data/tasks/ports/freetds.rb +1 -6
- data/tasks/ports/libiconv.rb +0 -17
- data/tasks/ports/openssl.rb +2 -18
- data/tasks/ports/recipe.rb +16 -4
- data/tasks/ports.rake +61 -40
- data/test/bin/install-mssql.ps1 +42 -0
- data/test/bin/install-mssqltools.sh +9 -0
- data/test/bin/setup_tinytds_db.sh +7 -0
- data/test/bin/setup_volume_permissions.sh +10 -0
- data/test/client_test.rb +101 -59
- data/test/gem_test.rb +25 -28
- data/test/result_test.rb +130 -182
- data/test/schema_test.rb +366 -388
- data/test/sql/db-create.sql +18 -0
- data/test/sql/db-login.sql +38 -0
- data/test/test_helper.rb +63 -31
- data/test/thread_test.rb +1 -1
- data/tiny_tds.gemspec +10 -7
- metadata +70 -52
- data/.travis.yml +0 -24
- data/BACKERS.md +0 -32
- data/appveyor.yml +0 -51
- data/test/appveyor/dbsetup.ps1 +0 -27
- data/test/appveyor/dbsetup.sql +0 -9
- data/test/bin/setup.sh +0 -19
- data/test/schema/sqlserver_2000.sql +0 -140
- data/test/schema/sqlserver_2005.sql +0 -140
- data/test/schema/sqlserver_2014.sql +0 -140
- data/test/schema/sqlserver_2016.sql +0 -140
- data/test/schema/sybase_ase.sql +0 -138
- /data/test/schema/{sqlserver_2008.sql → sqlserver_2017.sql} +0 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
|
5
|
+
sudo groupadd -g 3434 circleci_tinytds
|
6
|
+
sudo usermod -a -G circleci_tinytds $USER
|
7
|
+
sudo useradd circleci_tinytds -u 3434 -g 3434
|
8
|
+
sudo usermod -a -G circleci_tinytds circleci_tinytds
|
9
|
+
sudo chgrp -R circleci_tinytds .
|
10
|
+
sudo chmod -R g+rwx .
|
data/test/client_test.rb
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
require 'test_helper'
|
3
3
|
|
4
4
|
class ClientTest < TinyTds::TestCase
|
5
|
-
|
6
|
-
describe 'With valid credentials' do
|
7
|
-
|
5
|
+
describe 'with valid credentials' do
|
8
6
|
before do
|
9
7
|
@client = new_connection
|
10
8
|
end
|
@@ -18,6 +16,7 @@ class ClientTest < TinyTds::TestCase
|
|
18
16
|
assert @client.close
|
19
17
|
assert @client.closed?
|
20
18
|
assert !@client.active?
|
19
|
+
assert @client.dead?
|
21
20
|
action = lambda { @client.execute('SELECT 1 as [one]').each }
|
22
21
|
assert_raise_tinytds_error(action) do |e|
|
23
22
|
assert_match %r{closed connection}i, e.message, 'ignore if non-english test run'
|
@@ -25,10 +24,7 @@ class ClientTest < TinyTds::TestCase
|
|
25
24
|
end
|
26
25
|
|
27
26
|
it 'has getters for the tds version information (brittle since conf takes precedence)' do
|
28
|
-
if
|
29
|
-
assert_equal 7, @client.tds_version
|
30
|
-
assert_equal 'DBTDS_5_0 - 5.0 SQL Server', @client.tds_version_info
|
31
|
-
elsif @client.tds_73?
|
27
|
+
if @client.tds_73?
|
32
28
|
assert_equal 11, @client.tds_version
|
33
29
|
assert_equal 'DBTDS_7_3 - Microsoft SQL Server 2008', @client.tds_version_info
|
34
30
|
else
|
@@ -67,10 +63,12 @@ class ClientTest < TinyTds::TestCase
|
|
67
63
|
client.close if client
|
68
64
|
end
|
69
65
|
end unless sqlserver_azure?
|
70
|
-
|
71
66
|
end
|
72
67
|
|
73
68
|
describe 'With in-valid options' do
|
69
|
+
before(:all) do
|
70
|
+
init_toxiproxy
|
71
|
+
end
|
74
72
|
|
75
73
|
it 'raises an argument error when no :host given and :dataserver is blank' do
|
76
74
|
assert_raises(ArgumentError) { new_connection :dataserver => nil, :host => nil }
|
@@ -132,30 +130,63 @@ class ClientTest < TinyTds::TestCase
|
|
132
130
|
end
|
133
131
|
end
|
134
132
|
|
135
|
-
it '
|
136
|
-
skip
|
133
|
+
it 'raises TinyTds exception with tcp socket network failure' do
|
137
134
|
begin
|
138
|
-
client = new_connection :
|
135
|
+
client = new_connection timeout: 2, port: 1234, host: ENV['TOXIPROXY_HOST']
|
139
136
|
assert_client_works(client)
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
137
|
+
action = lambda { client.execute("waitfor delay '00:00:05'").do }
|
138
|
+
|
139
|
+
# Use toxiproxy to close the TCP socket after 1 second.
|
140
|
+
# We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel
|
141
|
+
# the network connection needs to close after the sql batch is sent and before the timeout above is hit
|
142
|
+
Toxiproxy[:sqlserver_test].toxic(:slow_close, delay: 1000).apply do
|
143
|
+
assert_raise_tinytds_error(action) do |e|
|
144
|
+
assert_equal 20003, e.db_error_number
|
145
|
+
assert_equal 6, e.severity
|
146
|
+
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
ensure
|
150
|
+
assert_new_connections_work
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'raises TinyTds exception with dead connection network failure' do
|
155
|
+
skip if ruby_windows?
|
156
|
+
|
157
|
+
begin
|
158
|
+
client = new_connection timeout: 2, port: 1234, host: ENV['TOXIPROXY_HOST']
|
159
|
+
assert_client_works(client)
|
160
|
+
action = lambda { client.execute("waitfor delay '00:00:05'").do }
|
161
|
+
|
162
|
+
# Use toxiproxy to close the network connection after 1 second.
|
163
|
+
# We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel
|
164
|
+
# the network connection needs to close after the sql batch is sent and before the timeout above is hit
|
165
|
+
Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 1000).apply do
|
166
|
+
assert_raise_tinytds_error(action) do |e|
|
167
|
+
assert_equal 20047, e.db_error_number
|
168
|
+
assert_includes [1,9], e.severity
|
169
|
+
assert_match %r{dead or not enabled}i, e.message, 'ignore if non-english test run'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
ensure
|
173
|
+
assert_new_connections_work
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'raises TinyTds exception with login timeout' do
|
178
|
+
begin
|
179
|
+
action = lambda do
|
180
|
+
Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 0).apply do
|
181
|
+
new_connection login_timeout: 1, port: 1234, host: ENV['TOXIPROXY_HOST']
|
182
|
+
end
|
183
|
+
end
|
144
184
|
assert_raise_tinytds_error(action) do |e|
|
145
185
|
assert_equal 20003, e.db_error_number
|
146
186
|
assert_equal 6, e.severity
|
147
187
|
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
148
188
|
end
|
149
189
|
ensure
|
150
|
-
STDOUT.puts "Reconnect network!"
|
151
|
-
sleep 10
|
152
|
-
action = lambda { client.execute('SELECT 1 as [one]').each }
|
153
|
-
assert_raise_tinytds_error(action) do |e|
|
154
|
-
assert_equal 20047, e.db_error_number
|
155
|
-
assert_equal 1, e.severity
|
156
|
-
assert_match %r{dead or not enabled}i, e.message, 'ignore if non-english test run'
|
157
|
-
end
|
158
|
-
close_client(client)
|
159
190
|
assert_new_connections_work
|
160
191
|
end
|
161
192
|
end
|
@@ -165,7 +196,7 @@ class ClientTest < TinyTds::TestCase
|
|
165
196
|
options = connection_options :username => 'willnotwork'
|
166
197
|
action = lambda { new_connection(options) }
|
167
198
|
assert_raise_tinytds_error(action) do |e|
|
168
|
-
assert_equal
|
199
|
+
assert_equal 18456, e.db_error_number
|
169
200
|
assert_equal 14, e.severity
|
170
201
|
assert_match %r{login failed}i, e.message, 'ignore if non-english test run'
|
171
202
|
end
|
@@ -174,57 +205,68 @@ class ClientTest < TinyTds::TestCase
|
|
174
205
|
|
175
206
|
end
|
176
207
|
|
177
|
-
describe '
|
178
|
-
|
208
|
+
describe '#parse_username' do
|
179
209
|
let(:client) { @client = new_connection }
|
180
210
|
|
181
|
-
it '
|
182
|
-
|
183
|
-
|
211
|
+
it 'returns username if azure is not true' do
|
212
|
+
_(
|
213
|
+
client.send(:parse_username, username: 'user@abc123.database.windows.net')
|
214
|
+
).must_equal 'user@abc123.database.windows.net'
|
184
215
|
end
|
185
216
|
|
186
|
-
it '
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
217
|
+
it 'returns short username if azure is true' do
|
218
|
+
_(
|
219
|
+
client.send(
|
220
|
+
:parse_username,
|
221
|
+
username: 'user@abc123.database.windows.net',
|
222
|
+
host: 'abc123.database.windows.net',
|
223
|
+
azure: true
|
224
|
+
)
|
191
225
|
).must_equal 'user@abc123'
|
192
226
|
end
|
193
227
|
|
194
|
-
it '
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
228
|
+
it 'returns full username if azure is false' do
|
229
|
+
_(
|
230
|
+
client.send(
|
231
|
+
:parse_username,
|
232
|
+
username: 'user@abc123.database.windows.net',
|
233
|
+
host: 'abc123.database.windows.net',
|
234
|
+
azure: false
|
235
|
+
)
|
199
236
|
).must_equal 'user@abc123.database.windows.net'
|
200
237
|
end
|
201
238
|
|
202
|
-
it '
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
239
|
+
it 'returns short username if passed and azure is true' do
|
240
|
+
_(
|
241
|
+
client.send(
|
242
|
+
:parse_username,
|
243
|
+
username: 'user@abc123',
|
244
|
+
host: 'abc123.database.windows.net',
|
245
|
+
azure: true
|
246
|
+
)
|
207
247
|
).must_equal 'user@abc123'
|
208
248
|
end
|
209
249
|
|
210
|
-
it '
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
250
|
+
it 'returns username with servername if passed and azure is true' do
|
251
|
+
_(
|
252
|
+
client.send(
|
253
|
+
:parse_username,
|
254
|
+
username: 'user',
|
255
|
+
host: 'abc123.database.windows.net',
|
256
|
+
azure: true
|
257
|
+
)
|
215
258
|
).must_equal 'user@abc123'
|
216
259
|
end
|
217
260
|
|
218
|
-
it '
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
261
|
+
it 'returns username with servername if passed and azure is false' do
|
262
|
+
_(
|
263
|
+
client.send(
|
264
|
+
:parse_username,
|
265
|
+
username: 'user',
|
266
|
+
host: 'abc123.database.windows.net',
|
267
|
+
azure: false
|
268
|
+
)
|
223
269
|
).must_equal 'user'
|
224
270
|
end
|
225
|
-
|
226
271
|
end
|
227
|
-
|
228
|
-
|
229
272
|
end
|
230
|
-
|
data/test/gem_test.rb
CHANGED
@@ -9,11 +9,11 @@ class GemTest < MiniTest::Spec
|
|
9
9
|
|
10
10
|
# We're going to muck with some system globals so lets make sure
|
11
11
|
# they get set back later
|
12
|
-
|
12
|
+
original_platform = RbConfig::CONFIG['arch']
|
13
13
|
original_pwd = Dir.pwd
|
14
14
|
|
15
15
|
after do
|
16
|
-
RbConfig::CONFIG['
|
16
|
+
RbConfig::CONFIG['arch'] = original_platform
|
17
17
|
Dir.chdir original_pwd
|
18
18
|
end
|
19
19
|
|
@@ -21,13 +21,13 @@ class GemTest < MiniTest::Spec
|
|
21
21
|
let(:root_path) { TinyTds::Gem.root_path }
|
22
22
|
|
23
23
|
it 'should be the root path' do
|
24
|
-
root_path.must_equal gem_root
|
24
|
+
_(root_path).must_equal gem_root
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'should be the root path no matter the cwd' do
|
28
28
|
Dir.chdir '/'
|
29
29
|
|
30
|
-
root_path.must_equal gem_root
|
30
|
+
_(root_path).must_equal gem_root
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -35,19 +35,19 @@ class GemTest < MiniTest::Spec
|
|
35
35
|
let(:ports_root_path) { TinyTds::Gem.ports_root_path }
|
36
36
|
|
37
37
|
it 'should be the ports path' do
|
38
|
-
ports_root_path.must_equal File.join(gem_root,'ports')
|
38
|
+
_(ports_root_path).must_equal File.join(gem_root,'ports')
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should be the ports path no matter the cwd' do
|
42
42
|
Dir.chdir '/'
|
43
43
|
|
44
|
-
ports_root_path.must_equal File.join(gem_root,'ports')
|
44
|
+
_(ports_root_path).must_equal File.join(gem_root,'ports')
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe '#ports_bin_paths' do
|
49
49
|
let(:ports_bin_paths) { TinyTds::Gem.ports_bin_paths }
|
50
|
-
|
50
|
+
|
51
51
|
describe 'when the ports directories exist' do
|
52
52
|
let(:fake_bin_paths) do
|
53
53
|
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
@@ -61,7 +61,7 @@ class GemTest < MiniTest::Spec
|
|
61
61
|
end
|
62
62
|
|
63
63
|
before do
|
64
|
-
RbConfig::CONFIG['
|
64
|
+
RbConfig::CONFIG['arch'] = 'fake-host-with-dirs'
|
65
65
|
fake_bin_paths.each do |path|
|
66
66
|
FileUtils.mkdir_p(path)
|
67
67
|
end
|
@@ -74,34 +74,34 @@ class GemTest < MiniTest::Spec
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'should return all the bin directories' do
|
77
|
-
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
77
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'should return all the bin directories regardless of cwd' do
|
81
81
|
Dir.chdir '/'
|
82
|
-
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
82
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
describe 'when the ports directories are missing' do
|
87
87
|
before do
|
88
|
-
RbConfig::CONFIG['
|
88
|
+
RbConfig::CONFIG['arch'] = 'fake-host-without-dirs'
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'should return no directories' do
|
92
|
-
ports_bin_paths.must_be_empty
|
92
|
+
_(ports_bin_paths).must_be_empty
|
93
93
|
end
|
94
94
|
|
95
95
|
it 'should return no directories regardless of cwd' do
|
96
96
|
Dir.chdir '/'
|
97
|
-
ports_bin_paths.must_be_empty
|
97
|
+
_(ports_bin_paths).must_be_empty
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
describe '#ports_lib_paths' do
|
103
103
|
let(:ports_lib_paths) { TinyTds::Gem.ports_lib_paths }
|
104
|
-
|
104
|
+
|
105
105
|
describe 'when the ports directories exist' do
|
106
106
|
let(:fake_lib_paths) do
|
107
107
|
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
@@ -115,7 +115,7 @@ class GemTest < MiniTest::Spec
|
|
115
115
|
end
|
116
116
|
|
117
117
|
before do
|
118
|
-
RbConfig::CONFIG['
|
118
|
+
RbConfig::CONFIG['arch'] = 'fake-host-with-dirs'
|
119
119
|
fake_lib_paths.each do |path|
|
120
120
|
FileUtils.mkdir_p(path)
|
121
121
|
end
|
@@ -128,48 +128,45 @@ class GemTest < MiniTest::Spec
|
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'should return all the lib directories' do
|
131
|
-
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
131
|
+
_(ports_lib_paths.sort).must_equal fake_lib_paths.sort
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'should return all the lib directories regardless of cwd' do
|
135
135
|
Dir.chdir '/'
|
136
|
-
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
136
|
+
_(ports_lib_paths.sort).must_equal fake_lib_paths.sort
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
140
|
describe 'when the ports directories are missing' do
|
141
141
|
before do
|
142
|
-
RbConfig::CONFIG['
|
142
|
+
RbConfig::CONFIG['arch'] = 'fake-host-without-dirs'
|
143
143
|
end
|
144
144
|
|
145
145
|
|
146
146
|
it 'should return no directories' do
|
147
|
-
ports_lib_paths.must_be_empty
|
147
|
+
_(ports_lib_paths).must_be_empty
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'should return no directories regardless of cwd' do
|
151
151
|
Dir.chdir '/'
|
152
|
-
ports_lib_paths.must_be_empty
|
152
|
+
_(ports_lib_paths).must_be_empty
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
157
|
describe '#ports_host' do
|
158
158
|
{
|
159
|
-
'
|
160
|
-
'
|
161
|
-
'
|
162
|
-
'x86_64-w64-mingw32' => 'x86_64-w64-mingw32',
|
163
|
-
# consolidate this host to our build w64-mingw32 arch
|
164
|
-
'i686-pc-mingw32' => 'i686-w64-mingw32'
|
159
|
+
'x64-mingw-ucrt' => 'x64-mingw-ucrt',
|
160
|
+
'x64-mingw32' => 'x64-mingw32',
|
161
|
+
'x86_64-linux' => 'x86_64-linux',
|
165
162
|
}.each do |host,expected|
|
166
163
|
describe "on a #{host} architecture" do
|
167
164
|
before do
|
168
|
-
RbConfig::CONFIG['
|
165
|
+
RbConfig::CONFIG['arch'] = host
|
169
166
|
end
|
170
167
|
|
171
168
|
it "should return a #{expected} ports host" do
|
172
|
-
TinyTds::Gem.ports_host.must_equal expected
|
169
|
+
_(TinyTds::Gem.ports_host).must_equal expected
|
173
170
|
end
|
174
171
|
end
|
175
172
|
end
|