vm_tiny_tds 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
+