tiny_tds 0.7.0 → 0.9.5.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/CHANGELOG +17 -46
- data/Gemfile +4 -0
- data/README.md +20 -14
- data/Rakefile +18 -13
- data/VERSION +1 -0
- data/appveyor.yml +17 -6
- data/bin/tsql +25 -0
- data/exe/.keep +0 -0
- data/ext/tiny_tds/client.c +26 -24
- data/ext/tiny_tds/client.h +1 -0
- data/ext/tiny_tds/extconf.rb +57 -36
- data/ext/tiny_tds/extconsts.rb +14 -0
- data/ext/tiny_tds/result.c +76 -36
- data/ext/tiny_tds/result.h +0 -4
- data/ext/tiny_tds/tiny_tds_ext.h +4 -2
- data/lib/tiny_tds.rb +3 -9
- data/lib/tiny_tds/client.rb +61 -34
- data/lib/tiny_tds/version.rb +1 -1
- data/ports/patches/freetds/0.91.112/Makefile.in.diff +29 -0
- data/ports/patches/freetds/0.91.112/dblib-30-char-username.diff +11 -0
- data/ports/patches/freetds/0.95.75/0001-mingw_missing_inet_pton.diff +34 -0
- data/test/client_test.rb +32 -12
- data/test/result_test.rb +13 -13
- data/test/schema/sqlserver_2000.sql +13 -13
- data/test/schema/sqlserver_2005.sql +13 -13
- data/test/schema/sqlserver_2008.sql +13 -13
- data/test/schema/sqlserver_2014.sql +9 -9
- data/test/schema/sqlserver_azure.sql +13 -13
- data/test/schema/sybase_ase.sql +7 -7
- data/test/schema_test.rb +157 -33
- data/test/test_helper.rb +13 -8
- data/test/thread_test.rb +6 -4
- metadata +37 -15
data/ext/tiny_tds/result.h
CHANGED
data/ext/tiny_tds/tiny_tds_ext.h
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
#ifndef TINYTDS_EXT
|
2
2
|
#define TINYTDS_EXT
|
3
3
|
|
4
|
-
#undef
|
5
|
-
#define
|
4
|
+
#undef SYBDBLIB
|
5
|
+
#define MSDBLIB 1
|
6
6
|
|
7
7
|
#include <ruby.h>
|
8
8
|
#include <ruby/encoding.h>
|
9
|
+
#include <ruby/version.h>
|
10
|
+
#include <ruby/thread.h>
|
9
11
|
#include <sybfront.h>
|
10
12
|
#include <sybdb.h>
|
11
13
|
|
data/lib/tiny_tds.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'date'
|
3
3
|
require 'bigdecimal'
|
4
|
-
require 'rational'
|
4
|
+
require 'rational'
|
5
5
|
|
6
6
|
require 'tiny_tds/version'
|
7
7
|
require 'tiny_tds/error'
|
@@ -15,8 +15,7 @@ if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
|
|
15
15
|
old_path = ENV['PATH']
|
16
16
|
begin
|
17
17
|
# Do the same host consolidation as in extconf.rb
|
18
|
-
ports_dir = RbConfig::CONFIG["host"].gsub('
|
19
|
-
gsub('i686-pc-mingw32', 'i686-w64-mingw32')
|
18
|
+
ports_dir = RbConfig::CONFIG["host"].gsub('i686-pc-mingw32', 'i686-w64-mingw32')
|
20
19
|
ENV['PATH'] = "#{File.expand_path("../../ports/#{ports_dir}/bin", __FILE__)};#{old_path}"
|
21
20
|
require "tiny_tds/#{ver}/tiny_tds"
|
22
21
|
rescue LoadError
|
@@ -31,12 +30,7 @@ else
|
|
31
30
|
ports_libs = File.expand_path("../../ports/#{RbConfig::CONFIG["host"]}/lib/*.so", __FILE__)
|
32
31
|
Dir[ports_libs].each do |lib|
|
33
32
|
require "fiddle"
|
34
|
-
|
35
|
-
Fiddle.dlopen(lib)
|
36
|
-
else
|
37
|
-
# For compat with Ruby < 2.0
|
38
|
-
DL.dlopen(lib)
|
39
|
-
end
|
33
|
+
Fiddle.dlopen(lib)
|
40
34
|
end
|
41
35
|
|
42
36
|
require 'tiny_tds/tiny_tds'
|
data/lib/tiny_tds/client.rb
CHANGED
@@ -1,39 +1,6 @@
|
|
1
1
|
module TinyTds
|
2
2
|
class Client
|
3
3
|
|
4
|
-
# From sybdb.h comments:
|
5
|
-
# DBVERSION_xxx are used with dbsetversion()
|
6
|
-
#
|
7
|
-
TDS_VERSIONS_SETTERS = {
|
8
|
-
'unknown' => 0,
|
9
|
-
'46' => 1,
|
10
|
-
'100' => 2,
|
11
|
-
'42' => 3,
|
12
|
-
'70' => 4,
|
13
|
-
'71' => 5,
|
14
|
-
'80' => 5,
|
15
|
-
'72' => 6,
|
16
|
-
'90' => 6
|
17
|
-
}.freeze
|
18
|
-
|
19
|
-
# From sybdb.h comments:
|
20
|
-
# DBTDS_xxx are returned by DBTDS()
|
21
|
-
# The integer values of the constants are poorly chosen.
|
22
|
-
#
|
23
|
-
TDS_VERSIONS_GETTERS = {
|
24
|
-
0 => {:name => 'DBTDS_UNKNOWN', :description => 'Unknown'},
|
25
|
-
1 => {:name => 'DBTDS_2_0', :description => 'Pre 4.0 SQL Server'},
|
26
|
-
2 => {:name => 'DBTDS_3_4', :description => 'Microsoft SQL Server (3.0)'},
|
27
|
-
3 => {:name => 'DBTDS_4_0', :description => '4.0 SQL Server'},
|
28
|
-
4 => {:name => 'DBTDS_4_2', :description => '4.2 SQL Server'},
|
29
|
-
5 => {:name => 'DBTDS_4_6', :description => '2.0 OpenServer and 4.6 SQL Server.'},
|
30
|
-
6 => {:name => 'DBTDS_4_9_5', :description => '4.9.5 (NCR) SQL Server'},
|
31
|
-
7 => {:name => 'DBTDS_5_0', :description => '5.0 SQL Server'},
|
32
|
-
8 => {:name => 'DBTDS_7_0', :description => 'Microsoft SQL Server 7.0'},
|
33
|
-
9 => {:name => 'DBTDS_7_1/DBTDS_8_0', :description => 'Microsoft SQL Server 2000'},
|
34
|
-
10 => {:name => 'DBTDS_7_2/DBTDS_9_0', :description => 'Microsoft SQL Server 2005'}
|
35
|
-
}.freeze
|
36
|
-
|
37
4
|
@@default_query_options = {
|
38
5
|
:as => :hash,
|
39
6
|
:symbolize_keys => false,
|
@@ -53,6 +20,7 @@ module TinyTds
|
|
53
20
|
# Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
|
54
21
|
# overide this method to return a string name that Encoding.find would work with. Default
|
55
22
|
# is to return the passed encoding.
|
23
|
+
#
|
56
24
|
def transpose_iconv_encoding(encoding)
|
57
25
|
encoding
|
58
26
|
end
|
@@ -62,10 +30,11 @@ module TinyTds
|
|
62
30
|
|
63
31
|
def initialize(opts={})
|
64
32
|
raise ArgumentError, 'missing :host option if no :dataserver given' if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
|
33
|
+
opts[:username] = parse_username(opts)
|
65
34
|
@query_options = @@default_query_options.dup
|
66
35
|
opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ''
|
67
36
|
opts[:appname] ||= 'TinyTds'
|
68
|
-
opts[:tds_version] =
|
37
|
+
opts[:tds_version] = tds_versions_setter(opts)
|
69
38
|
opts[:login_timeout] ||= 60
|
70
39
|
opts[:timeout] ||= 5
|
71
40
|
opts[:encoding] = (opts[:encoding].nil? || opts[:encoding].downcase == 'utf8') ? 'UTF-8' : opts[:encoding].upcase
|
@@ -74,6 +43,10 @@ module TinyTds
|
|
74
43
|
connect(opts)
|
75
44
|
end
|
76
45
|
|
46
|
+
def tds_73?
|
47
|
+
tds_version >= 11
|
48
|
+
end
|
49
|
+
|
77
50
|
def tds_version_info
|
78
51
|
info = TDS_VERSIONS_GETTERS[tds_version]
|
79
52
|
"#{info[:name]} - #{info[:description]}" if info
|
@@ -90,5 +63,59 @@ module TinyTds
|
|
90
63
|
::Time.local(2010).utc_offset.to_r / 86400
|
91
64
|
end
|
92
65
|
|
66
|
+
def parse_username(opts)
|
67
|
+
username = opts[:username]
|
68
|
+
return username if username.nil? || !opts[:azure] || !username.include?("@")
|
69
|
+
user, domain = username.split("@")
|
70
|
+
"#{user}@#{domain.split('.').first}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def tds_versions_setter(opts={})
|
74
|
+
v = opts[:tds_version] || ENV['TDSVER'] || '7.1'
|
75
|
+
TDS_VERSIONS_SETTERS[v.to_s]
|
76
|
+
end
|
77
|
+
|
78
|
+
# From sybdb.h comments:
|
79
|
+
# DBVERSION_xxx are used with dbsetversion()
|
80
|
+
#
|
81
|
+
TDS_VERSIONS_SETTERS = {
|
82
|
+
'unknown' => 0,
|
83
|
+
'46' => 1,
|
84
|
+
'100' => 2,
|
85
|
+
'42' => 3,
|
86
|
+
'70' => 4,
|
87
|
+
'7.0' => 4,
|
88
|
+
'71' => 5,
|
89
|
+
'7.1' => 5,
|
90
|
+
'80' => 5,
|
91
|
+
'8.0' => 5,
|
92
|
+
'72' => 6,
|
93
|
+
'7.2' => 6,
|
94
|
+
'90' => 6,
|
95
|
+
'9.0' => 6,
|
96
|
+
'73' => 7,
|
97
|
+
'7.3' => 7
|
98
|
+
}.freeze
|
99
|
+
|
100
|
+
# From sybdb.h comments:
|
101
|
+
# DBTDS_xxx are returned by DBTDS()
|
102
|
+
# The integer values of the constants are poorly chosen.
|
103
|
+
#
|
104
|
+
TDS_VERSIONS_GETTERS = {
|
105
|
+
0 => {:name => 'DBTDS_UNKNOWN', :description => 'Unknown'},
|
106
|
+
1 => {:name => 'DBTDS_2_0', :description => 'Pre 4.0 SQL Server'},
|
107
|
+
2 => {:name => 'DBTDS_3_4', :description => 'Microsoft SQL Server (3.0)'},
|
108
|
+
3 => {:name => 'DBTDS_4_0', :description => '4.0 SQL Server'},
|
109
|
+
4 => {:name => 'DBTDS_4_2', :description => '4.2 SQL Server'},
|
110
|
+
5 => {:name => 'DBTDS_4_6', :description => '2.0 OpenServer and 4.6 SQL Server.'},
|
111
|
+
6 => {:name => 'DBTDS_4_9_5', :description => '4.9.5 (NCR) SQL Server'},
|
112
|
+
7 => {:name => 'DBTDS_5_0', :description => '5.0 SQL Server'},
|
113
|
+
8 => {:name => 'DBTDS_7_0', :description => 'Microsoft SQL Server 7.0'},
|
114
|
+
9 => {:name => 'DBTDS_7_1/DBTDS_8_0', :description => 'Microsoft SQL Server 2000'},
|
115
|
+
10 => {:name => 'DBTDS_7_2/DBTDS_9_0', :description => 'Microsoft SQL Server 2005'},
|
116
|
+
11 => {:name => 'DBTDS_7_3', :description => 'Microsoft SQL Server 2008'},
|
117
|
+
12 => {:name => 'DBTDS_7_4', :description => 'Microsoft SQL Server 2012/2014'}
|
118
|
+
}.freeze
|
119
|
+
|
93
120
|
end
|
94
121
|
end
|
data/lib/tiny_tds/version.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
--- a/Makefile.in 2011-08-17 18:57:36.000000000 -0700
|
2
|
+
+++ b/Makefile.in 2014-05-02 10:27:01.275813000 -0700
|
3
|
+
@@ -772,13 +772,6 @@
|
4
|
+
|
5
|
+
|
6
|
+
install-data-local:
|
7
|
+
- $(mkinstalldirs) $(ETC)
|
8
|
+
- if test ! -f $(ETC)/freetds.conf; then \
|
9
|
+
- $(INSTALL_DATA) $(srcdir)/freetds.conf $(ETC)/freetds.conf; \
|
10
|
+
- fi
|
11
|
+
- if test ! -f $(ETC)/locales.conf; then \
|
12
|
+
- $(INSTALL_DATA) $(srcdir)/locales.conf $(ETC)/locales.conf; \
|
13
|
+
- fi
|
14
|
+
|
15
|
+
clean-local:
|
16
|
+
find . \( -name \*.test_output -o -name \*.bb -o -name \*.bbg -o -name \*.da -o -name \*.gc\* \) -exec rm -f {} \;
|
17
|
+
--- a/src/pool/Makefile.in 2011-08-17 18:57:36.000000000 -0700
|
18
|
+
+++ b/src/pool/Makefile.in 2014-05-02 10:32:39.628347600 -0700
|
19
|
+
@@ -574,10 +574,6 @@
|
20
|
+
|
21
|
+
|
22
|
+
install-data-local:
|
23
|
+
- $(mkinstalldirs) $(ETC)
|
24
|
+
- if test ! -f $(ETC)/pool.conf; then \
|
25
|
+
- $(INSTALL_DATA) $(srcdir)/pool.conf $(ETC)/pool.conf; \
|
26
|
+
- fi
|
27
|
+
|
28
|
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
29
|
+
# Otherwise a system limit (for SysV at least) may be exceeded.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
--- a/src/dblib/dblib.c
|
2
|
+
+++ b/src/dblib/dblib.c
|
3
|
+
@@ -765,7 +765,7 @@ dbsetlname(LOGINREC * login, const char *value, int which)
|
4
|
+
return FAIL;
|
5
|
+
}
|
6
|
+
|
7
|
+
- if (TDS_MAX_LOGIN_STR_SZ < strlen(value)) {
|
8
|
+
+ if (login->tds_login->tds_version < 0x700 && TDS_MAX_LOGIN_STR_SZ < strlen(value)) {
|
9
|
+
dbperror(NULL, SYBENTLL, 0);
|
10
|
+
return FAIL;
|
11
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
diff --git a/src/tds/tls.c b/src/tds/tls.c
|
2
|
+
index 0d11a33..b8ab2ba 100644
|
3
|
+
--- a/src/tds/tls.c
|
4
|
+
+++ b/src/tds/tls.c
|
5
|
+
@@ -72,6 +72,29 @@
|
6
|
+
#define SSL_PTR bio->ptr
|
7
|
+
#endif
|
8
|
+
|
9
|
+
+/*
|
10
|
+
+ * Add a workaround for older Mingw versions without inet_pton().
|
11
|
+
+ * This means RubyInstallers DevKit-4.7.2 in particular.
|
12
|
+
+ */
|
13
|
+
+#if defined(__MINGW64_VERSION_MAJOR) && !defined(InetPtonA)
|
14
|
+
+ #include <windows.h>
|
15
|
+
+
|
16
|
+
+ static HMODULE ws2_32 = NULL;
|
17
|
+
+ typedef INT (WINAPI * __inet_pton)(INT Family, LPCWSTR pStringBuf, PVOID pAddr);
|
18
|
+
+ static __inet_pton _inet_pton = NULL;
|
19
|
+
+
|
20
|
+
+ INT WINAPI inet_pton(INT Family, LPCWSTR pStringBuf, PVOID pAddr)
|
21
|
+
+ {
|
22
|
+
+ if (_inet_pton == NULL) {
|
23
|
+
+ ws2_32 = LoadLibraryEx("Ws2_32.dll", NULL, 0);
|
24
|
+
+
|
25
|
+
+ _inet_pton = (__inet_pton)GetProcAddress(ws2_32, "inet_pton");
|
26
|
+
+ }
|
27
|
+
+
|
28
|
+
+ return (_inet_pton)(Family, pStringBuf, pAddr);
|
29
|
+
+ }
|
30
|
+
+#endif
|
31
|
+
+
|
32
|
+
static SSL_RET
|
33
|
+
tds_pull_func_login(SSL_PULL_ARGS)
|
34
|
+
{
|
data/test/client_test.rb
CHANGED
@@ -28,6 +28,9 @@ class ClientTest < TinyTds::TestCase
|
|
28
28
|
if sybase_ase?
|
29
29
|
assert_equal 7, @client.tds_version
|
30
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
|
31
34
|
else
|
32
35
|
assert_equal 9, @client.tds_version
|
33
36
|
assert_equal 'DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000', @client.tds_version_info
|
@@ -48,6 +51,7 @@ class ClientTest < TinyTds::TestCase
|
|
48
51
|
client = new_connection(:encoding => encoding)
|
49
52
|
assert_equal encoding, client.charset
|
50
53
|
assert_equal Encoding.find(encoding), client.encoding
|
54
|
+
client.close
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -55,6 +59,7 @@ class ClientTest < TinyTds::TestCase
|
|
55
59
|
host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST']
|
56
60
|
port = ENV['TINYTDS_UNIT_PORT_TEST'] || ENV['TINYTDS_UNIT_PORT'] || 1433
|
57
61
|
client = new_connection dataserver: nil, host: host, port: port
|
62
|
+
client.close
|
58
63
|
end unless sqlserver_azure?
|
59
64
|
|
60
65
|
end
|
@@ -89,6 +94,7 @@ class ClientTest < TinyTds::TestCase
|
|
89
94
|
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
90
95
|
end
|
91
96
|
assert_client_works(client)
|
97
|
+
close_client(client)
|
92
98
|
assert_new_connections_work
|
93
99
|
end
|
94
100
|
|
@@ -97,6 +103,7 @@ class ClientTest < TinyTds::TestCase
|
|
97
103
|
client.execute("WaitFor Delay '00:00:01'").do
|
98
104
|
client.execute("WaitFor Delay '00:00:01'").do
|
99
105
|
client.execute("WaitFor Delay '00:00:01'").do
|
106
|
+
close_client(client)
|
100
107
|
end
|
101
108
|
|
102
109
|
it 'must not timeout per sql batch when under transaction' do
|
@@ -108,6 +115,7 @@ class ClientTest < TinyTds::TestCase
|
|
108
115
|
client.execute("WaitFor Delay '00:00:01'").do
|
109
116
|
ensure
|
110
117
|
client.execute("COMMIT TRANSACTION").do
|
118
|
+
close_client(client)
|
111
119
|
end
|
112
120
|
end
|
113
121
|
|
@@ -134,6 +142,7 @@ class ClientTest < TinyTds::TestCase
|
|
134
142
|
assert_equal 1, e.severity
|
135
143
|
assert_match %r{dead or not enabled}i, e.message, 'ignore if non-english test run'
|
136
144
|
end
|
145
|
+
close_client(client)
|
137
146
|
assert_new_connections_work
|
138
147
|
end
|
139
148
|
end
|
@@ -143,7 +152,9 @@ class ClientTest < TinyTds::TestCase
|
|
143
152
|
action = lambda { new_connection(options) }
|
144
153
|
assert_raise_tinytds_error(action) do |e|
|
145
154
|
if sqlserver_azure?
|
146
|
-
|
155
|
+
assert_equal 40532, e.db_error_number
|
156
|
+
assert_equal 20, e.severity
|
157
|
+
assert_match %r{login failed}i, e.message, 'ignore if non-english test run'
|
147
158
|
else
|
148
159
|
assert_equal sybase_ase? ? 4002 : 18456, e.db_error_number
|
149
160
|
assert_equal 14, e.severity
|
@@ -153,19 +164,28 @@ class ClientTest < TinyTds::TestCase
|
|
153
164
|
assert_new_connections_work
|
154
165
|
end
|
155
166
|
|
156
|
-
it 'fails miserably with unknown encoding option' do
|
157
|
-
options = connection_options :encoding => 'ISO-WTF'
|
158
|
-
action = lambda { new_connection(options) }
|
159
|
-
assert_raise_tinytds_error(action) do |e|
|
160
|
-
assert_equal 20002, e.db_error_number
|
161
|
-
assert_equal 9, e.severity
|
162
|
-
assert_match %r{connection failed}i, e.message, 'ignore if non-english test run'
|
163
|
-
end
|
164
|
-
assert_new_connections_work
|
165
|
-
end unless sybase_ase?
|
166
|
-
|
167
167
|
end
|
168
168
|
|
169
|
+
describe 'Private methods' do
|
170
|
+
|
171
|
+
let(:client) { @client = new_connection }
|
172
|
+
|
173
|
+
it '#parse_username returns username if azure is not true' do
|
174
|
+
username = 'user@long.domain.name.com'
|
175
|
+
client.send(:parse_username, username: username).must_equal username
|
176
|
+
end
|
177
|
+
|
178
|
+
it '#parse_username returns short username if azure is true' do
|
179
|
+
username = 'user@long.domain.name.com'
|
180
|
+
client.send(:parse_username, username: username, azure: true).must_equal 'user@long'
|
181
|
+
end
|
182
|
+
|
183
|
+
it '#parse_username returns short username if passed and azure is true' do
|
184
|
+
username = 'user@short'
|
185
|
+
client.send(:parse_username, username: username, azure: true).must_equal 'user@short'
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
169
189
|
|
170
190
|
|
171
191
|
end
|
data/test/result_test.rb
CHANGED
@@ -397,6 +397,7 @@ class ResultTest < TinyTds::TestCase
|
|
397
397
|
describe 'using :empty_sets TRUE' do
|
398
398
|
|
399
399
|
before do
|
400
|
+
close_client
|
400
401
|
@old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
|
401
402
|
TinyTds::Client.default_query_options[:empty_sets] = true
|
402
403
|
@client = new_connection
|
@@ -477,6 +478,7 @@ class ResultTest < TinyTds::TestCase
|
|
477
478
|
describe 'using :empty_sets FALSE' do
|
478
479
|
|
479
480
|
before do
|
481
|
+
close_client
|
480
482
|
@old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
|
481
483
|
TinyTds::Client.default_query_options[:empty_sets] = false
|
482
484
|
@client = new_connection
|
@@ -668,12 +670,14 @@ class ResultTest < TinyTds::TestCase
|
|
668
670
|
end
|
669
671
|
|
670
672
|
it 'must not error at all from reading non-convertable charcters and just use ? marks' do
|
673
|
+
close_client
|
671
674
|
@client = new_connection :encoding => 'ASCII'
|
672
675
|
@client.charset.must_equal 'ASCII'
|
673
676
|
find_value(202, :nvarchar_50).must_equal 'test nvarchar_50 ??'
|
674
677
|
end
|
675
678
|
|
676
679
|
it 'must error gracefully from writing non-convertable characters' do
|
680
|
+
close_client
|
677
681
|
@client = new_connection :encoding => 'ASCII'
|
678
682
|
@client.charset.must_equal 'ASCII'
|
679
683
|
rollback_transaction(@client) do
|
@@ -681,26 +685,22 @@ class ResultTest < TinyTds::TestCase
|
|
681
685
|
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
682
686
|
action = lambda { @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES ('#{text}')").do }
|
683
687
|
assert_raise_tinytds_error(action) do |e|
|
684
|
-
e.message.must_match %r{
|
685
|
-
e.severity.must_equal
|
686
|
-
e.db_error_number.must_equal
|
688
|
+
e.message.must_match %r{Unclosed quotation mark}i
|
689
|
+
e.severity.must_equal 15
|
690
|
+
e.db_error_number.must_equal 105
|
687
691
|
end
|
688
692
|
assert_followup_query
|
689
693
|
end
|
690
694
|
end
|
691
695
|
|
692
696
|
it 'errors gracefully with incorrect syntax in sp_executesql' do
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
assert_equal 156, e.db_error_number
|
699
|
-
end
|
700
|
-
assert_followup_query
|
701
|
-
else
|
702
|
-
skip 'FreeTDS 0.91 and higher can only pass this test.'
|
697
|
+
action = lambda { @client.execute("EXEC sp_executesql N'this will not work'").each }
|
698
|
+
assert_raise_tinytds_error(action) do |e|
|
699
|
+
assert_match %r|incorrect syntax|i, e.message
|
700
|
+
assert_equal 15, e.severity
|
701
|
+
assert_equal 156, e.db_error_number
|
703
702
|
end
|
703
|
+
assert_followup_query
|
704
704
|
end unless sybase_ase?
|
705
705
|
|
706
706
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
|
2
2
|
/*
|
3
3
|
|
4
|
-
* Binary Data - Our test binary data is a 1 pixel gif. The basic (raw) data is below. Quoting this data
|
5
|
-
would involve this (encode) method and be (encoded) with the 0x prefix for raw SQL. In other clients the
|
4
|
+
* Binary Data - Our test binary data is a 1 pixel gif. The basic (raw) data is below. Quoting this data
|
5
|
+
would involve this (encode) method and be (encoded) with the 0x prefix for raw SQL. In other clients the
|
6
6
|
(raw_db) value without the 0x prefix would need to be (packed) again yield the original (raw) value.
|
7
|
-
|
7
|
+
|
8
8
|
(raw) - "GIF89a\001\000\001\000\221\000\000\377\377\377\377\377\377\376\001\002\000\000\000!\371\004\004\024\000\377\000,\000\000\000\000\001\000\001\000\000\002\002D\001\000;"
|
9
9
|
(encode) - "0x#{raw.unpack("H*")[0]}"
|
10
10
|
(encoded) - "0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
11
11
|
(raw_db) - "47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
12
12
|
(packed) - [raw_db].pack('H*')
|
13
|
-
|
13
|
+
|
14
14
|
*/
|
15
15
|
|
16
16
|
CREATE TABLE [dbo].[datatypes] (
|
@@ -70,13 +70,13 @@ INSERT INTO [datatypes] ([id], [char_10]) VALUES ( 42, '12345678' )
|
|
70
70
|
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 61, '1753-01-01T00:00:00.000' )
|
71
71
|
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 62, '9999-12-31T23:59:59.997' )
|
72
72
|
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 63, '2010-01-01T12:34:56.123' )
|
73
|
-
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 71, '0001-01-
|
74
|
-
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 72, '1984-01-
|
75
|
-
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 73, '9999-12-
|
76
|
-
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 81, '1984-01-24T04:20:00.
|
73
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 71, '0001-01-01 00:00:00.0000000' )
|
74
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 72, '1984-01-24 04:20:00.0000000' )
|
75
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 73, '9999-12-31 23:59:59.9999999' )
|
76
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 81, '1984-01-24T04:20:00.1234567-08:00' ) -- 1984-01-24 04:20:00.00 -08:00
|
77
77
|
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 82, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.00 +00:00
|
78
78
|
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 83, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.99 +00:00
|
79
|
-
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 84, '1984-01-24T04:20:00.
|
79
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 84, '1984-01-24T04:20:00.1234567-08:00' ) -- 1984-01-24 04:20:00.1234567 -08:00
|
80
80
|
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 85, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.0000000 +00:00
|
81
81
|
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 86, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.9999999 +00:00
|
82
82
|
INSERT INTO [datatypes] ([id], [decimal_9_2]) VALUES ( 91, 12345.01 )
|
@@ -120,10 +120,10 @@ INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 251, 4.20 )
|
|
120
120
|
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 252, -214748.3647 )
|
121
121
|
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 253, 214748.3646 )
|
122
122
|
INSERT INTO [datatypes] ([id], [text]) VALUES ( 271, 'test text' )
|
123
|
-
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 281, '
|
124
|
-
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 282, '
|
125
|
-
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 283, '
|
126
|
-
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 284, '
|
123
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 281, '15:45:00.709714966' ) -- 15:45:00.71
|
124
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 282, '04:20:00.288321545' ) -- 04:20:00.29
|
125
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 283, '15:45:00.709714966' ) -- 15:45:00.709714900
|
126
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 284, '04:20:00.288321545' ) -- 04:20:00.288321500
|
127
127
|
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 301, 0 )
|
128
128
|
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 302, 255 )
|
129
129
|
INSERT INTO [datatypes] ([id], [uniqueidentifier]) VALUES ( 311, NEWID() )
|