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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +20 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +20 -0
  5. data/.rubocop.yml +31 -0
  6. data/.travis.yml +24 -0
  7. data/BACKERS.md +32 -0
  8. data/CHANGELOG.md +255 -0
  9. data/CODE_OF_CONDUCT.md +31 -0
  10. data/Gemfile +9 -0
  11. data/ISSUE_TEMPLATE.md +38 -0
  12. data/MIT-LICENSE +23 -0
  13. data/README.md +504 -0
  14. data/Rakefile +53 -0
  15. data/VERSION +1 -0
  16. data/appveyor.yml +51 -0
  17. data/bin/defncopy-ttds +3 -0
  18. data/bin/tsql-ttds +3 -0
  19. data/exe/.keep +0 -0
  20. data/ext/tiny_tds/client.c +451 -0
  21. data/ext/tiny_tds/client.h +51 -0
  22. data/ext/tiny_tds/extconf.rb +69 -0
  23. data/ext/tiny_tds/extconsts.rb +15 -0
  24. data/ext/tiny_tds/result.c +619 -0
  25. data/ext/tiny_tds/result.h +32 -0
  26. data/ext/tiny_tds/tiny_tds_ext.c +12 -0
  27. data/ext/tiny_tds/tiny_tds_ext.h +17 -0
  28. data/lib/tiny_tds/bin.rb +104 -0
  29. data/lib/tiny_tds/client.rb +136 -0
  30. data/lib/tiny_tds/error.rb +14 -0
  31. data/lib/tiny_tds/gem.rb +32 -0
  32. data/lib/tiny_tds/result.rb +7 -0
  33. data/lib/tiny_tds/version.rb +3 -0
  34. data/lib/tiny_tds.rb +61 -0
  35. data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +34 -0
  36. data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
  37. data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
  38. data/tasks/native_gem.rake +14 -0
  39. data/tasks/package.rake +8 -0
  40. data/tasks/ports/freetds.rb +37 -0
  41. data/tasks/ports/libiconv.rb +43 -0
  42. data/tasks/ports/openssl.rb +78 -0
  43. data/tasks/ports/recipe.rb +52 -0
  44. data/tasks/ports.rake +87 -0
  45. data/tasks/test.rake +9 -0
  46. data/test/appveyor/dbsetup.ps1 +27 -0
  47. data/test/appveyor/dbsetup.sql +9 -0
  48. data/test/benchmark/query.rb +77 -0
  49. data/test/benchmark/query_odbc.rb +106 -0
  50. data/test/benchmark/query_tinytds.rb +126 -0
  51. data/test/bin/install-freetds.sh +20 -0
  52. data/test/bin/install-openssl.sh +18 -0
  53. data/test/bin/setup.sh +19 -0
  54. data/test/client_test.rb +230 -0
  55. data/test/gem_test.rb +179 -0
  56. data/test/result_test.rb +773 -0
  57. data/test/schema/1px.gif +0 -0
  58. data/test/schema/sqlserver_2000.sql +140 -0
  59. data/test/schema/sqlserver_2005.sql +140 -0
  60. data/test/schema/sqlserver_2008.sql +140 -0
  61. data/test/schema/sqlserver_2014.sql +140 -0
  62. data/test/schema/sqlserver_2016.sql +140 -0
  63. data/test/schema/sqlserver_azure.sql +140 -0
  64. data/test/schema/sybase_ase.sql +138 -0
  65. data/test/schema_test.rb +443 -0
  66. data/test/test_helper.rb +217 -0
  67. data/test/thread_test.rb +98 -0
  68. data/tiny_tds.gemspec +29 -0
  69. metadata +225 -0
@@ -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
+