tiny_tds 3.2.0-aarch64-linux-gnu
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/.github/workflows/ci.yml +590 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +31 -0
- data/CHANGELOG.md +305 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/Gemfile +2 -0
- data/ISSUE_TEMPLATE.md +38 -0
- data/MIT-LICENSE +23 -0
- data/README.md +493 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/bin/defncopy-ttds +3 -0
- data/bin/tsql-ttds +3 -0
- data/docker-compose.yml +34 -0
- data/exe/.keep +0 -0
- data/ext/tiny_tds/client.c +492 -0
- data/ext/tiny_tds/client.h +53 -0
- data/ext/tiny_tds/extconf.rb +190 -0
- data/ext/tiny_tds/extconsts.rb +8 -0
- data/ext/tiny_tds/result.c +626 -0
- data/ext/tiny_tds/result.h +32 -0
- data/ext/tiny_tds/tiny_tds_ext.c +15 -0
- data/ext/tiny_tds/tiny_tds_ext.h +17 -0
- data/lib/tiny_tds/2.7/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.0/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.1/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.2/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.3/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.4/tiny_tds.so +0 -0
- data/lib/tiny_tds/bin.rb +90 -0
- data/lib/tiny_tds/client.rb +132 -0
- data/lib/tiny_tds/error.rb +12 -0
- data/lib/tiny_tds/gem.rb +23 -0
- data/lib/tiny_tds/result.rb +5 -0
- data/lib/tiny_tds/version.rb +3 -0
- data/lib/tiny_tds.rb +42 -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/ports/aarch64-linux-gnu/bin/defncopy +0 -0
- data/ports/aarch64-linux-gnu/bin/tsql +0 -0
- data/ports/aarch64-linux-gnu/lib/libsybdb.so.5 +0 -0
- data/setup_cimgruby_dev.sh +25 -0
- data/start_dev.sh +21 -0
- data/tasks/native_gem.rake +16 -0
- data/tasks/package.rake +6 -0
- data/tasks/ports.rake +24 -0
- data/tasks/test.rake +7 -0
- data/test/bin/install-freetds.sh +18 -0
- data/test/bin/install-mssql.ps1 +42 -0
- data/test/bin/install-mssqltools.sh +9 -0
- data/test/bin/install-openssl.sh +18 -0
- data/test/bin/restore-from-native-gem.ps1 +10 -0
- data/test/bin/setup_tinytds_db.sh +7 -0
- data/test/bin/setup_volume_permissions.sh +10 -0
- data/test/client_test.rb +266 -0
- data/test/gem_test.rb +100 -0
- data/test/result_test.rb +708 -0
- data/test/schema/1px.gif +0 -0
- data/test/schema/sqlserver_2017.sql +140 -0
- data/test/schema/sqlserver_azure.sql +140 -0
- data/test/schema_test.rb +417 -0
- data/test/sql/db-create.sql +18 -0
- data/test/sql/db-login.sql +38 -0
- data/test/test_helper.rb +244 -0
- data/test/thread_test.rb +89 -0
- data/tiny_tds.gemspec +31 -0
- metadata +259 -0
data/test/client_test.rb
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ClientTest < TinyTds::TestCase
|
4
|
+
describe "with valid credentials" do
|
5
|
+
before do
|
6
|
+
@client = new_connection
|
7
|
+
end
|
8
|
+
|
9
|
+
it "must not be closed" do
|
10
|
+
assert !@client.closed?
|
11
|
+
assert @client.active?
|
12
|
+
end
|
13
|
+
|
14
|
+
it "allows client connection to be closed" do
|
15
|
+
assert @client.close
|
16
|
+
assert @client.closed?
|
17
|
+
assert !@client.active?
|
18
|
+
assert @client.dead?
|
19
|
+
action = lambda { @client.execute("SELECT 1 as [one]").each }
|
20
|
+
assert_raise_tinytds_error(action) do |e|
|
21
|
+
assert_match %r{closed connection}i, e.message, "ignore if non-english test run"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has getters for the tds version information (brittle since conf takes precedence)" do
|
26
|
+
if @client.tds_73?
|
27
|
+
assert_equal 11, @client.tds_version
|
28
|
+
assert_equal "DBTDS_7_3 - Microsoft SQL Server 2008", @client.tds_version_info
|
29
|
+
else
|
30
|
+
assert_equal 9, @client.tds_version
|
31
|
+
assert_equal "DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000", @client.tds_version_info
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "uses UTF-8 client charset/encoding by default" do
|
36
|
+
assert_equal "UTF-8", @client.charset
|
37
|
+
assert_equal Encoding.find("UTF-8"), @client.encoding
|
38
|
+
end
|
39
|
+
|
40
|
+
it "has a #escape method used for quote strings" do
|
41
|
+
assert_equal "''hello''", @client.escape("'hello'")
|
42
|
+
end
|
43
|
+
|
44
|
+
["CP850", "CP1252", "ISO-8859-1"].each do |encoding|
|
45
|
+
it "allows valid iconv character set - #{encoding}" do
|
46
|
+
client = new_connection(encoding: encoding)
|
47
|
+
assert_equal encoding, client.charset
|
48
|
+
assert_equal Encoding.find(encoding), client.encoding
|
49
|
+
ensure
|
50
|
+
client&.close
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
unless sqlserver_azure?
|
55
|
+
it "must be able to use :host/:port connection" do
|
56
|
+
host = ENV["TINYTDS_UNIT_HOST_TEST"] || ENV["TINYTDS_UNIT_HOST"] || "localhost"
|
57
|
+
port = ENV["TINYTDS_UNIT_PORT_TEST"] || ENV["TINYTDS_UNIT_PORT"] || 1433
|
58
|
+
begin
|
59
|
+
client = new_connection dataserver: nil, host: host, port: port
|
60
|
+
ensure
|
61
|
+
client&.close
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "With in-valid options" do
|
68
|
+
before(:all) do
|
69
|
+
init_toxiproxy
|
70
|
+
end
|
71
|
+
|
72
|
+
it "raises an argument error when no :host given and :dataserver is blank" do
|
73
|
+
assert_raises(ArgumentError) { new_connection dataserver: nil, host: nil }
|
74
|
+
end
|
75
|
+
|
76
|
+
it "raises an argument error when no :username is supplied" do
|
77
|
+
assert_raises(ArgumentError) { TinyTds::Client.new username: nil }
|
78
|
+
end
|
79
|
+
|
80
|
+
it "raises TinyTds exception with undefined :dataserver" do
|
81
|
+
options = connection_options login_timeout: 1, dataserver: "DOESNOTEXIST"
|
82
|
+
action = lambda { new_connection(options) }
|
83
|
+
assert_raise_tinytds_error(action) do |e|
|
84
|
+
# Not sure why tese are different.
|
85
|
+
if ruby_darwin?
|
86
|
+
assert_equal 20009, e.db_error_number
|
87
|
+
assert_equal 9, e.severity
|
88
|
+
assert_match %r{is unavailable or does not exist}i, e.message, "ignore if non-english test run"
|
89
|
+
else
|
90
|
+
assert_equal 20012, e.db_error_number
|
91
|
+
assert_equal 2, e.severity
|
92
|
+
assert_match %r{server name not found in configuration files}i, e.message, "ignore if non-english test run"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
assert_new_connections_work
|
96
|
+
end
|
97
|
+
|
98
|
+
it "raises TinyTds exception with long query past :timeout option" do
|
99
|
+
client = new_connection timeout: 1
|
100
|
+
action = lambda { client.execute("WaitFor Delay '00:00:02'").do }
|
101
|
+
assert_raise_tinytds_error(action) do |e|
|
102
|
+
assert_equal 20003, e.db_error_number
|
103
|
+
assert_equal 6, e.severity
|
104
|
+
assert_match %r{timed out}i, e.message, "ignore if non-english test run"
|
105
|
+
end
|
106
|
+
assert_client_works(client)
|
107
|
+
close_client(client)
|
108
|
+
assert_new_connections_work
|
109
|
+
end
|
110
|
+
|
111
|
+
it "must not timeout per sql batch when not under transaction" do
|
112
|
+
client = new_connection timeout: 2
|
113
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
114
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
115
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
116
|
+
close_client(client)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "must not timeout per sql batch when under transaction" do
|
120
|
+
client = new_connection timeout: 2
|
121
|
+
begin
|
122
|
+
client.execute("BEGIN TRANSACTION").do
|
123
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
124
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
125
|
+
client.execute("WaitFor Delay '00:00:01'").do
|
126
|
+
ensure
|
127
|
+
client.execute("COMMIT TRANSACTION").do
|
128
|
+
close_client(client)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it "raises TinyTds exception with tcp socket network failure" do
|
133
|
+
client = new_connection timeout: 2, port: 1234, host: ENV["TOXIPROXY_HOST"]
|
134
|
+
assert_client_works(client)
|
135
|
+
action = lambda { client.execute("waitfor delay '00:00:05'").do }
|
136
|
+
|
137
|
+
# Use toxiproxy to close the TCP socket after 1 second.
|
138
|
+
# We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel
|
139
|
+
# the network connection needs to close after the sql batch is sent and before the timeout above is hit
|
140
|
+
Toxiproxy[:sqlserver_test].toxic(:slow_close, delay: 1000).apply do
|
141
|
+
assert_raise_tinytds_error(action) do |e|
|
142
|
+
assert_equal 20003, e.db_error_number
|
143
|
+
assert_equal 6, e.severity
|
144
|
+
assert_match %r{timed out}i, e.message, "ignore if non-english test run"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
ensure
|
148
|
+
assert_new_connections_work
|
149
|
+
end
|
150
|
+
|
151
|
+
it "raises TinyTds exception with dead connection network failure" do
|
152
|
+
skip if ruby_windows?
|
153
|
+
|
154
|
+
begin
|
155
|
+
client = new_connection timeout: 2, port: 1234, host: ENV["TOXIPROXY_HOST"]
|
156
|
+
assert_client_works(client)
|
157
|
+
action = lambda { client.execute("waitfor delay '00:00:05'").do }
|
158
|
+
|
159
|
+
# Use toxiproxy to close the network connection after 1 second.
|
160
|
+
# We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel
|
161
|
+
# the network connection needs to close after the sql batch is sent and before the timeout above is hit
|
162
|
+
Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 1000).apply do
|
163
|
+
assert_raise_tinytds_error(action) do |e|
|
164
|
+
assert_equal 20047, e.db_error_number
|
165
|
+
assert_includes [1, 9], e.severity
|
166
|
+
assert_match %r{dead or not enabled}i, e.message, "ignore if non-english test run"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
ensure
|
170
|
+
assert_new_connections_work
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it "raises TinyTds exception with login timeout" do
|
175
|
+
action = lambda do
|
176
|
+
Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 0).apply do
|
177
|
+
new_connection login_timeout: 1, port: 1234, host: ENV["TOXIPROXY_HOST"]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
assert_raise_tinytds_error(action) do |e|
|
181
|
+
assert_equal 20003, e.db_error_number
|
182
|
+
assert_equal 6, e.severity
|
183
|
+
assert_match %r{timed out}i, e.message, "ignore if non-english test run"
|
184
|
+
end
|
185
|
+
ensure
|
186
|
+
assert_new_connections_work
|
187
|
+
end
|
188
|
+
|
189
|
+
it "raises TinyTds exception with wrong :username" do
|
190
|
+
skip if ENV["CI"] && sqlserver_azure? # Some issue with db_error_number.
|
191
|
+
options = connection_options username: "willnotwork"
|
192
|
+
action = lambda { new_connection(options) }
|
193
|
+
assert_raise_tinytds_error(action) do |e|
|
194
|
+
assert_equal 18456, e.db_error_number
|
195
|
+
assert_equal 14, e.severity
|
196
|
+
assert_match %r{login failed}i, e.message, "ignore if non-english test run"
|
197
|
+
end
|
198
|
+
assert_new_connections_work
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "#parse_username" do
|
203
|
+
let(:client) { @client = new_connection }
|
204
|
+
|
205
|
+
it "returns username if azure is not true" do
|
206
|
+
_(
|
207
|
+
client.send(:parse_username, username: "user@abc123.database.windows.net")
|
208
|
+
).must_equal "user@abc123.database.windows.net"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "returns short username if azure is true" do
|
212
|
+
_(
|
213
|
+
client.send(
|
214
|
+
:parse_username,
|
215
|
+
username: "user@abc123.database.windows.net",
|
216
|
+
host: "abc123.database.windows.net",
|
217
|
+
azure: true
|
218
|
+
)
|
219
|
+
).must_equal "user@abc123"
|
220
|
+
end
|
221
|
+
|
222
|
+
it "returns full username if azure is false" do
|
223
|
+
_(
|
224
|
+
client.send(
|
225
|
+
:parse_username,
|
226
|
+
username: "user@abc123.database.windows.net",
|
227
|
+
host: "abc123.database.windows.net",
|
228
|
+
azure: false
|
229
|
+
)
|
230
|
+
).must_equal "user@abc123.database.windows.net"
|
231
|
+
end
|
232
|
+
|
233
|
+
it "returns short username if passed and azure is true" do
|
234
|
+
_(
|
235
|
+
client.send(
|
236
|
+
:parse_username,
|
237
|
+
username: "user@abc123",
|
238
|
+
host: "abc123.database.windows.net",
|
239
|
+
azure: true
|
240
|
+
)
|
241
|
+
).must_equal "user@abc123"
|
242
|
+
end
|
243
|
+
|
244
|
+
it "returns username with servername if passed and azure is true" do
|
245
|
+
_(
|
246
|
+
client.send(
|
247
|
+
:parse_username,
|
248
|
+
username: "user",
|
249
|
+
host: "abc123.database.windows.net",
|
250
|
+
azure: true
|
251
|
+
)
|
252
|
+
).must_equal "user@abc123"
|
253
|
+
end
|
254
|
+
|
255
|
+
it "returns username with servername if passed and azure is false" do
|
256
|
+
_(
|
257
|
+
client.send(
|
258
|
+
:parse_username,
|
259
|
+
username: "user",
|
260
|
+
host: "abc123.database.windows.net",
|
261
|
+
azure: false
|
262
|
+
)
|
263
|
+
).must_equal "user"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
data/test/gem_test.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "tiny_tds/gem"
|
3
|
+
|
4
|
+
class GemTest < Minitest::Spec
|
5
|
+
gem_root ||= File.expand_path "../..", __FILE__
|
6
|
+
|
7
|
+
describe TinyTds::Gem do
|
8
|
+
# We're going to muck with some system globals so lets make sure
|
9
|
+
# they get set back later
|
10
|
+
original_platform = RbConfig::CONFIG["arch"]
|
11
|
+
original_pwd = Dir.pwd
|
12
|
+
|
13
|
+
after do
|
14
|
+
RbConfig::CONFIG["arch"] = original_platform
|
15
|
+
Dir.chdir original_pwd
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#root_path" do
|
19
|
+
let(:root_path) { TinyTds::Gem.root_path }
|
20
|
+
|
21
|
+
it "should be the root path" do
|
22
|
+
_(root_path).must_equal gem_root
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be the root path no matter the cwd" do
|
26
|
+
Dir.chdir "/"
|
27
|
+
|
28
|
+
_(root_path).must_equal gem_root
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#ports_root_path" do
|
33
|
+
let(:ports_root_path) { TinyTds::Gem.ports_root_path }
|
34
|
+
|
35
|
+
it "should be the ports path" do
|
36
|
+
_(ports_root_path).must_equal File.join(gem_root, "ports")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be the ports path no matter the cwd" do
|
40
|
+
Dir.chdir "/"
|
41
|
+
|
42
|
+
_(ports_root_path).must_equal File.join(gem_root, "ports")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#ports_bin_paths" do
|
47
|
+
let(:ports_bin_paths) { TinyTds::Gem.ports_bin_paths }
|
48
|
+
|
49
|
+
describe "when the ports directories exist" do
|
50
|
+
let(:fake_bin_paths) do
|
51
|
+
ports_host_root = File.join(gem_root, "ports", "fake-host-with-dirs")
|
52
|
+
[
|
53
|
+
File.join("a", "bin"),
|
54
|
+
File.join("a", "inner", "bin"),
|
55
|
+
File.join("b", "bin")
|
56
|
+
].map do |p|
|
57
|
+
File.join(ports_host_root, p)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
before do
|
62
|
+
RbConfig::CONFIG["arch"] = "fake-host-with-dirs"
|
63
|
+
fake_bin_paths.each do |path|
|
64
|
+
FileUtils.mkdir_p(path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
after do
|
69
|
+
FileUtils.remove_entry_secure(
|
70
|
+
File.join(gem_root, "ports", "fake-host-with-dirs"), true
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return all the bin directories" do
|
75
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return all the bin directories regardless of cwd" do
|
79
|
+
Dir.chdir "/"
|
80
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "when the ports directories are missing" do
|
85
|
+
before do
|
86
|
+
RbConfig::CONFIG["arch"] = "fake-host-without-dirs"
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return no directories" do
|
90
|
+
_(ports_bin_paths).must_be_empty
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return no directories regardless of cwd" do
|
94
|
+
Dir.chdir "/"
|
95
|
+
_(ports_bin_paths).must_be_empty
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|