vm_tiny_tds 2.1.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 +7 -0
- data/.codeclimate.yml +20 -0
- data/.gitattributes +1 -0
- data/.gitignore +20 -0
- data/.rubocop.yml +31 -0
- data/.travis.yml +24 -0
- data/BACKERS.md +32 -0
- data/CHANGELOG.md +255 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/Gemfile +9 -0
- data/ISSUE_TEMPLATE.md +38 -0
- data/MIT-LICENSE +23 -0
- data/README.md +504 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/appveyor.yml +51 -0
- data/bin/defncopy-ttds +3 -0
- data/bin/tsql-ttds +3 -0
- data/exe/.keep +0 -0
- data/ext/tiny_tds/client.c +451 -0
- data/ext/tiny_tds/client.h +51 -0
- data/ext/tiny_tds/extconf.rb +69 -0
- data/ext/tiny_tds/extconsts.rb +15 -0
- data/ext/tiny_tds/result.c +619 -0
- data/ext/tiny_tds/result.h +32 -0
- data/ext/tiny_tds/tiny_tds_ext.c +12 -0
- data/ext/tiny_tds/tiny_tds_ext.h +17 -0
- data/lib/tiny_tds/bin.rb +104 -0
- data/lib/tiny_tds/client.rb +136 -0
- data/lib/tiny_tds/error.rb +14 -0
- data/lib/tiny_tds/gem.rb +32 -0
- data/lib/tiny_tds/result.rb +7 -0
- data/lib/tiny_tds/version.rb +3 -0
- data/lib/tiny_tds.rb +61 -0
- data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +34 -0
- data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
- data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
- data/tasks/native_gem.rake +14 -0
- data/tasks/package.rake +8 -0
- data/tasks/ports/freetds.rb +37 -0
- data/tasks/ports/libiconv.rb +43 -0
- data/tasks/ports/openssl.rb +78 -0
- data/tasks/ports/recipe.rb +52 -0
- data/tasks/ports.rake +87 -0
- data/tasks/test.rake +9 -0
- data/test/appveyor/dbsetup.ps1 +27 -0
- data/test/appveyor/dbsetup.sql +9 -0
- data/test/benchmark/query.rb +77 -0
- data/test/benchmark/query_odbc.rb +106 -0
- data/test/benchmark/query_tinytds.rb +126 -0
- data/test/bin/install-freetds.sh +20 -0
- data/test/bin/install-openssl.sh +18 -0
- data/test/bin/setup.sh +19 -0
- data/test/client_test.rb +230 -0
- data/test/gem_test.rb +179 -0
- data/test/result_test.rb +773 -0
- data/test/schema/1px.gif +0 -0
- data/test/schema/sqlserver_2000.sql +140 -0
- data/test/schema/sqlserver_2005.sql +140 -0
- data/test/schema/sqlserver_2008.sql +140 -0
- data/test/schema/sqlserver_2014.sql +140 -0
- data/test/schema/sqlserver_2016.sql +140 -0
- data/test/schema/sqlserver_azure.sql +140 -0
- data/test/schema/sybase_ase.sql +138 -0
- data/test/schema_test.rb +443 -0
- data/test/test_helper.rb +217 -0
- data/test/thread_test.rb +98 -0
- data/tiny_tds.gemspec +29 -0
- metadata +225 -0
data/test/client_test.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class ClientTest < TinyTds::TestCase
|
5
|
+
|
6
|
+
describe 'With valid credentials' do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@client = new_connection
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'must not be closed' do
|
13
|
+
assert !@client.closed?
|
14
|
+
assert @client.active?
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'allows client connection to be closed' do
|
18
|
+
assert @client.close
|
19
|
+
assert @client.closed?
|
20
|
+
assert !@client.active?
|
21
|
+
action = lambda { @client.execute('SELECT 1 as [one]').each }
|
22
|
+
assert_raise_tinytds_error(action) do |e|
|
23
|
+
assert_match %r{closed connection}i, e.message, 'ignore if non-english test run'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'has getters for the tds version information (brittle since conf takes precedence)' do
|
28
|
+
if sybase_ase?
|
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?
|
32
|
+
assert_equal 11, @client.tds_version
|
33
|
+
assert_equal 'DBTDS_7_3 - Microsoft SQL Server 2008', @client.tds_version_info
|
34
|
+
else
|
35
|
+
assert_equal 9, @client.tds_version
|
36
|
+
assert_equal 'DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000', @client.tds_version_info
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'uses UTF-8 client charset/encoding by default' do
|
41
|
+
assert_equal 'UTF-8', @client.charset
|
42
|
+
assert_equal Encoding.find('UTF-8'), @client.encoding
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has a #escape method used for quote strings' do
|
46
|
+
assert_equal "''hello''", @client.escape("'hello'")
|
47
|
+
end
|
48
|
+
|
49
|
+
['CP850', 'CP1252', 'ISO-8859-1'].each do |encoding|
|
50
|
+
it "allows valid iconv character set - #{encoding}" do
|
51
|
+
begin
|
52
|
+
client = new_connection(:encoding => encoding)
|
53
|
+
assert_equal encoding, client.charset
|
54
|
+
assert_equal Encoding.find(encoding), client.encoding
|
55
|
+
ensure
|
56
|
+
client.close if client
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'must be able to use :host/:port connection' do
|
62
|
+
host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST'] || 'localhost'
|
63
|
+
port = ENV['TINYTDS_UNIT_PORT_TEST'] || ENV['TINYTDS_UNIT_PORT'] || 1433
|
64
|
+
begin
|
65
|
+
client = new_connection dataserver: nil, host: host, port: port
|
66
|
+
ensure
|
67
|
+
client.close if client
|
68
|
+
end
|
69
|
+
end unless sqlserver_azure?
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'With in-valid options' do
|
74
|
+
|
75
|
+
it 'raises an argument error when no :host given and :dataserver is blank' do
|
76
|
+
assert_raises(ArgumentError) { new_connection :dataserver => nil, :host => nil }
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'raises an argument error when no :username is supplied' do
|
80
|
+
assert_raises(ArgumentError) { TinyTds::Client.new :username => nil }
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'raises TinyTds exception with undefined :dataserver' do
|
84
|
+
options = connection_options :login_timeout => 1, :dataserver => 'DOESNOTEXIST'
|
85
|
+
action = lambda { new_connection(options) }
|
86
|
+
assert_raise_tinytds_error(action) do |e|
|
87
|
+
# Not sure why tese are different.
|
88
|
+
if ruby_darwin?
|
89
|
+
assert_equal 20009, e.db_error_number
|
90
|
+
assert_equal 9, e.severity
|
91
|
+
assert_match %r{is unavailable or does not exist}i, e.message, 'ignore if non-english test run'
|
92
|
+
else
|
93
|
+
assert_equal 20012, e.db_error_number
|
94
|
+
assert_equal 2, e.severity
|
95
|
+
assert_match %r{server name not found in configuration files}i, e.message, 'ignore if non-english test run'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
assert_new_connections_work
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'raises TinyTds exception with long query past :timeout option' do
|
102
|
+
client = new_connection :timeout => 1
|
103
|
+
action = lambda { client.execute("WaitFor Delay '00:00:02'").do }
|
104
|
+
assert_raise_tinytds_error(action) do |e|
|
105
|
+
assert_equal 20003, e.db_error_number
|
106
|
+
assert_equal 6, e.severity
|
107
|
+
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
108
|
+
end
|
109
|
+
assert_client_works(client)
|
110
|
+
close_client(client)
|
111
|
+
assert_new_connections_work
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'must not timeout per sql batch when not under transaction' do
|
115
|
+
client = new_connection :timeout => 2
|
116
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
117
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
118
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
119
|
+
close_client(client)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'must not timeout per sql batch when under transaction' do
|
123
|
+
client = new_connection :timeout => 2
|
124
|
+
begin
|
125
|
+
client.execute("BEGIN TRANSACTION").do
|
126
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
127
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
128
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
129
|
+
ensure
|
130
|
+
client.execute("COMMIT TRANSACTION").do
|
131
|
+
close_client(client)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'must run this test to prove we account for dropped connections' do
|
136
|
+
skip
|
137
|
+
begin
|
138
|
+
client = new_connection :login_timeout => 2, :timeout => 2
|
139
|
+
assert_client_works(client)
|
140
|
+
STDOUT.puts "Disconnect network!"
|
141
|
+
sleep 10
|
142
|
+
STDOUT.puts "This should not get stuck past 6 seconds!"
|
143
|
+
action = lambda { client.execute('SELECT 1 as [one]').each }
|
144
|
+
assert_raise_tinytds_error(action) do |e|
|
145
|
+
assert_equal 20003, e.db_error_number
|
146
|
+
assert_equal 6, e.severity
|
147
|
+
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
148
|
+
end
|
149
|
+
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
|
+
assert_new_connections_work
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'raises TinyTds exception with wrong :username' do
|
164
|
+
skip if ENV['CI'] && sqlserver_azure? # Some issue with db_error_number.
|
165
|
+
options = connection_options :username => 'willnotwork'
|
166
|
+
action = lambda { new_connection(options) }
|
167
|
+
assert_raise_tinytds_error(action) do |e|
|
168
|
+
assert_equal sybase_ase? ? 4002 : 18456, e.db_error_number
|
169
|
+
assert_equal 14, e.severity
|
170
|
+
assert_match %r{login failed}i, e.message, 'ignore if non-english test run'
|
171
|
+
end
|
172
|
+
assert_new_connections_work
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'Private methods' do
|
178
|
+
|
179
|
+
let(:client) { @client = new_connection }
|
180
|
+
|
181
|
+
it '#parse_username returns username if azure is not true' do
|
182
|
+
username = 'user@abc123.database.windows.net'
|
183
|
+
client.send(:parse_username, username: username).must_equal username
|
184
|
+
end
|
185
|
+
|
186
|
+
it '#parse_username returns short username if azure is true' do
|
187
|
+
client.send(:parse_username,
|
188
|
+
username: 'user@abc123.database.windows.net',
|
189
|
+
host: 'abc123.database.windows.net',
|
190
|
+
azure: true
|
191
|
+
).must_equal 'user@abc123'
|
192
|
+
end
|
193
|
+
|
194
|
+
it '#parse_username returns full username if azure is false' do
|
195
|
+
client.send(:parse_username,
|
196
|
+
username: 'user@abc123.database.windows.net',
|
197
|
+
host: 'abc123.database.windows.net',
|
198
|
+
azure: false
|
199
|
+
).must_equal 'user@abc123.database.windows.net'
|
200
|
+
end
|
201
|
+
|
202
|
+
it '#parse_username returns short username if passed and azure is true' do
|
203
|
+
client.send(:parse_username,
|
204
|
+
username: 'user@abc123',
|
205
|
+
host: 'abc123.database.windows.net',
|
206
|
+
azure: true
|
207
|
+
).must_equal 'user@abc123'
|
208
|
+
end
|
209
|
+
|
210
|
+
it '#parse_username returns username with servername if passed and azure is true' do
|
211
|
+
client.send(:parse_username,
|
212
|
+
username: 'user',
|
213
|
+
host: 'abc123.database.windows.net',
|
214
|
+
azure: true
|
215
|
+
).must_equal 'user@abc123'
|
216
|
+
end
|
217
|
+
|
218
|
+
it '#parse_username returns username with servername if passed and azure is false' do
|
219
|
+
client.send(:parse_username,
|
220
|
+
username: 'user',
|
221
|
+
host: 'abc123.database.windows.net',
|
222
|
+
azure: false
|
223
|
+
).must_equal 'user'
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
end
|
230
|
+
|
data/test/gem_test.rb
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
require 'tiny_tds/gem'
|
4
|
+
|
5
|
+
class GemTest < MiniTest::Spec
|
6
|
+
gem_root ||= File.expand_path '../..', __FILE__
|
7
|
+
|
8
|
+
describe TinyTds::Gem do
|
9
|
+
|
10
|
+
# We're going to muck with some system globals so lets make sure
|
11
|
+
# they get set back later
|
12
|
+
original_host = RbConfig::CONFIG['host']
|
13
|
+
original_pwd = Dir.pwd
|
14
|
+
|
15
|
+
after do
|
16
|
+
RbConfig::CONFIG['host'] = original_host
|
17
|
+
Dir.chdir original_pwd
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#root_path' do
|
21
|
+
let(:root_path) { TinyTds::Gem.root_path }
|
22
|
+
|
23
|
+
it 'should be the root path' do
|
24
|
+
root_path.must_equal gem_root
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should be the root path no matter the cwd' do
|
28
|
+
Dir.chdir '/'
|
29
|
+
|
30
|
+
root_path.must_equal gem_root
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#ports_root_path' do
|
35
|
+
let(:ports_root_path) { TinyTds::Gem.ports_root_path }
|
36
|
+
|
37
|
+
it 'should be the ports path' do
|
38
|
+
ports_root_path.must_equal File.join(gem_root,'ports')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should be the ports path no matter the cwd' do
|
42
|
+
Dir.chdir '/'
|
43
|
+
|
44
|
+
ports_root_path.must_equal File.join(gem_root,'ports')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#ports_bin_paths' do
|
49
|
+
let(:ports_bin_paths) { TinyTds::Gem.ports_bin_paths }
|
50
|
+
|
51
|
+
describe 'when the ports directories exist' do
|
52
|
+
let(:fake_bin_paths) do
|
53
|
+
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
54
|
+
[
|
55
|
+
File.join('a','bin'),
|
56
|
+
File.join('a','inner','bin'),
|
57
|
+
File.join('b','bin')
|
58
|
+
].map do |p|
|
59
|
+
File.join(ports_host_root, p)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
before do
|
64
|
+
RbConfig::CONFIG['host'] = 'fake-host-with-dirs'
|
65
|
+
fake_bin_paths.each do |path|
|
66
|
+
FileUtils.mkdir_p(path)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
after do
|
71
|
+
FileUtils.remove_entry_secure(
|
72
|
+
File.join(gem_root, 'ports', 'fake-host-with-dirs'), true
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return all the bin directories' do
|
77
|
+
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should return all the bin directories regardless of cwd' do
|
81
|
+
Dir.chdir '/'
|
82
|
+
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'when the ports directories are missing' do
|
87
|
+
before do
|
88
|
+
RbConfig::CONFIG['host'] = 'fake-host-without-dirs'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return no directories' do
|
92
|
+
ports_bin_paths.must_be_empty
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should return no directories regardless of cwd' do
|
96
|
+
Dir.chdir '/'
|
97
|
+
ports_bin_paths.must_be_empty
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#ports_lib_paths' do
|
103
|
+
let(:ports_lib_paths) { TinyTds::Gem.ports_lib_paths }
|
104
|
+
|
105
|
+
describe 'when the ports directories exist' do
|
106
|
+
let(:fake_lib_paths) do
|
107
|
+
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
108
|
+
[
|
109
|
+
File.join('a','lib'),
|
110
|
+
File.join('a','inner','lib'),
|
111
|
+
File.join('b','lib')
|
112
|
+
].map do |p|
|
113
|
+
File.join(ports_host_root, p)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
before do
|
118
|
+
RbConfig::CONFIG['host'] = 'fake-host-with-dirs'
|
119
|
+
fake_lib_paths.each do |path|
|
120
|
+
FileUtils.mkdir_p(path)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
after do
|
125
|
+
FileUtils.remove_entry_secure(
|
126
|
+
File.join(gem_root, 'ports', 'fake-host-with-dirs'), true
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should return all the lib directories' do
|
131
|
+
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should return all the lib directories regardless of cwd' do
|
135
|
+
Dir.chdir '/'
|
136
|
+
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'when the ports directories are missing' do
|
141
|
+
before do
|
142
|
+
RbConfig::CONFIG['host'] = 'fake-host-without-dirs'
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
it 'should return no directories' do
|
147
|
+
ports_lib_paths.must_be_empty
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should return no directories regardless of cwd' do
|
151
|
+
Dir.chdir '/'
|
152
|
+
ports_lib_paths.must_be_empty
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#ports_host' do
|
158
|
+
{
|
159
|
+
'i686-pc-linux-gnu' => 'i686-pc-linux-gnu',
|
160
|
+
'x86_64-pc-linux-gnu' => 'x86_64-pc-linux-gnu',
|
161
|
+
'i686-w64-mingw32' => 'i686-w64-mingw32',
|
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'
|
165
|
+
}.each do |host,expected|
|
166
|
+
describe "on a #{host} architecture" do
|
167
|
+
before do
|
168
|
+
RbConfig::CONFIG['host'] = host
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should return a #{expected} ports host" do
|
172
|
+
TinyTds::Gem.ports_host.must_equal expected
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|