tiny_tds 2.1.0.pre3 → 2.1.0.pre4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +1 -1
- data/VERSION +1 -1
- data/ext/tiny_tds/client.c +40 -22
- data/ext/tiny_tds/client.h +2 -1
- data/ext/tiny_tds/extconsts.rb +4 -4
- data/ext/tiny_tds/result.c +1 -0
- data/lib/tiny_tds/client.rb +7 -0
- data/test/bin/install-freetds.sh +1 -1
- data/test/client_test.rb +1 -1
- data/test/result_test.rb +40 -0
- data/test/test_helper.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae946f0a8582c1105d1a9927d9866e228cce17fe
|
4
|
+
data.tar.gz: 8763fb92c497e4cd0781be3292ad6ea1567cfead
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3038107c41dc1aefc11dfaef02b1a9608b97bcb3b0f3ce4a243d209335bab85e00c5ffb0f982c5da145286000c9d9f0c7c931166c732d2f84192250917ed4bc1
|
7
|
+
data.tar.gz: 1cca1065fd05681606e5a5eb24aaa3ed02d2e3a17bcf9352255b068a9d354e36e0a6a31683c4fc1cd0bc678bc9dfa509d4694a9a33fb987882b070d9c92e091a
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
* Support the FREETDS_DIR environment variable. Fixes #371.
|
5
5
|
* Rename binstubs to tsql-ttds and defncopy-ttds
|
6
6
|
* Support separate timeout values per connection Fixes #348.
|
7
|
+
* Allow client proc to capture INFO messages. Fixes #352.
|
8
|
+
* Use official HTTP mirrors instead of FTP. Fixes #384.
|
7
9
|
|
8
10
|
|
9
11
|
## 2.0.0
|
data/README.md
CHANGED
@@ -44,7 +44,7 @@ $ apt-get wget
|
|
44
44
|
$ apt-get install build-essential
|
45
45
|
$ apt-get install libc6-dev
|
46
46
|
|
47
|
-
$ wget
|
47
|
+
$ wget http://www.freetds.org/files/stable/freetds-1.00.21.tar.gz
|
48
48
|
$ tar -xzf freetds-1.00.21.tar.gz
|
49
49
|
$ cd freetds-1.00.21
|
50
50
|
$ ./configure --prefix=/usr/local --with-tdsver=7.3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.0.
|
1
|
+
2.1.0.pre4
|
data/ext/tiny_tds/client.c
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
VALUE cTinyTdsClient;
|
5
5
|
extern VALUE mTinyTds, cTinyTdsError;
|
6
|
-
static ID sym_username, sym_password, sym_dataserver, sym_database, sym_appname, sym_tds_version, sym_login_timeout, sym_timeout, sym_encoding, sym_azure, sym_contained, sym_use_utf16;
|
6
|
+
static ID sym_username, sym_password, sym_dataserver, sym_database, sym_appname, sym_tds_version, sym_login_timeout, sym_timeout, sym_encoding, sym_azure, sym_contained, sym_use_utf16, sym_message_handler;
|
7
7
|
static ID intern_source_eql, intern_severity_eql, intern_db_error_number_eql, intern_os_error_number_eql;
|
8
|
-
static ID intern_new, intern_dup, intern_transpose_iconv_encoding, intern_local_offset, intern_gsub;
|
8
|
+
static ID intern_new, intern_dup, intern_transpose_iconv_encoding, intern_local_offset, intern_gsub, intern_call;
|
9
9
|
VALUE opt_escape_regex, opt_escape_dblquote;
|
10
|
+
VALUE message_handler;
|
10
11
|
|
11
12
|
|
12
13
|
// Lib Macros
|
@@ -24,7 +25,7 @@ VALUE opt_escape_regex, opt_escape_dblquote;
|
|
24
25
|
|
25
26
|
// Lib Backend (Helpers)
|
26
27
|
|
27
|
-
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, const char *error, const char *source, int severity, int dberr, int oserr) {
|
28
|
+
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int is_message, int cancel, const char *error, const char *source, int severity, int dberr, int oserr) {
|
28
29
|
VALUE e;
|
29
30
|
GET_CLIENT_USERDATA(dbproc);
|
30
31
|
if (cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
|
@@ -41,6 +42,15 @@ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, const char *error, c
|
|
41
42
|
rb_funcall(e, intern_db_error_number_eql, 1, INT2FIX(dberr));
|
42
43
|
if (oserr)
|
43
44
|
rb_funcall(e, intern_os_error_number_eql, 1, INT2FIX(oserr));
|
45
|
+
|
46
|
+
if (severity <= 10 && is_message) {
|
47
|
+
if (message_handler && message_handler != Qnil && rb_respond_to(message_handler, intern_call) != 0) {
|
48
|
+
rb_funcall(message_handler, intern_call, 1, e);
|
49
|
+
}
|
50
|
+
|
51
|
+
return Qnil;
|
52
|
+
}
|
53
|
+
|
44
54
|
rb_exc_raise(e);
|
45
55
|
return Qnil;
|
46
56
|
}
|
@@ -109,6 +119,7 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
109
119
|
generic message can be sent.
|
110
120
|
*/
|
111
121
|
if (!userdata->nonblocking_error.is_set) {
|
122
|
+
userdata->nonblocking_error.is_message = 0;
|
112
123
|
userdata->nonblocking_error.cancel = cancel;
|
113
124
|
strncpy(userdata->nonblocking_error.error, dberrstr, ERROR_MSG_SIZE);
|
114
125
|
strncpy(userdata->nonblocking_error.source, source, ERROR_MSG_SIZE);
|
@@ -119,7 +130,7 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
119
130
|
}
|
120
131
|
|
121
132
|
} else {
|
122
|
-
rb_tinytds_raise_error(dbproc, cancel, dberrstr, source, severity, dberr, oserr);
|
133
|
+
rb_tinytds_raise_error(dbproc, 0, cancel, dberrstr, source, severity, dberr, oserr);
|
123
134
|
}
|
124
135
|
|
125
136
|
return return_value;
|
@@ -128,25 +139,28 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
128
139
|
int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) {
|
129
140
|
static const char *source = "message";
|
130
141
|
GET_CLIENT_USERDATA(dbproc);
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
userdata->dbcancel_sent = 1;
|
146
|
-
}
|
147
|
-
} else {
|
148
|
-
rb_tinytds_raise_error(dbproc, 1, msgtext, source, severity, msgno, msgstate);
|
142
|
+
|
143
|
+
int is_message_an_error = severity > 10 ? 1 : 0;
|
144
|
+
|
145
|
+
// See tinytds_err_handler() for info about why we do this
|
146
|
+
if (userdata && userdata->nonblocking) {
|
147
|
+
if (!userdata->nonblocking_error.is_set) {
|
148
|
+
userdata->nonblocking_error.is_message = !is_message_an_error;
|
149
|
+
userdata->nonblocking_error.cancel = is_message_an_error;
|
150
|
+
strncpy(userdata->nonblocking_error.error, msgtext, ERROR_MSG_SIZE);
|
151
|
+
strncpy(userdata->nonblocking_error.source, source, ERROR_MSG_SIZE);
|
152
|
+
userdata->nonblocking_error.severity = severity;
|
153
|
+
userdata->nonblocking_error.dberr = msgno;
|
154
|
+
userdata->nonblocking_error.oserr = msgstate;
|
155
|
+
userdata->nonblocking_error.is_set = 1;
|
149
156
|
}
|
157
|
+
|
158
|
+
if (is_message_an_error && !dbdead(dbproc) && !userdata->closed) {
|
159
|
+
dbcancel(dbproc);
|
160
|
+
userdata->dbcancel_sent = 1;
|
161
|
+
}
|
162
|
+
} else {
|
163
|
+
rb_tinytds_raise_error(dbproc, !is_message_an_error, is_message_an_error, msgtext, source, severity, msgno, msgstate);
|
150
164
|
}
|
151
165
|
return 0;
|
152
166
|
}
|
@@ -308,6 +322,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
308
322
|
azure = rb_hash_aref(opts, sym_azure);
|
309
323
|
contained = rb_hash_aref(opts, sym_contained);
|
310
324
|
use_utf16 = rb_hash_aref(opts, sym_use_utf16);
|
325
|
+
message_handler = rb_hash_aref(opts, sym_message_handler);
|
311
326
|
/* Dealing with options. */
|
312
327
|
if (dbinit() == FAIL) {
|
313
328
|
rb_raise(cTinyTdsError, "failed dbinit() function");
|
@@ -350,6 +365,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
350
365
|
rb_warn("TinyTds: :use_utf16 option not supported in this version of FreeTDS.\n");
|
351
366
|
}
|
352
367
|
#endif
|
368
|
+
|
353
369
|
cwrap->client = dbopen(cwrap->login, StringValueCStr(dataserver));
|
354
370
|
if (cwrap->client) {
|
355
371
|
VALUE transposed_encoding, timeout_string;
|
@@ -414,6 +430,7 @@ void init_tinytds_client() {
|
|
414
430
|
sym_azure = ID2SYM(rb_intern("azure"));
|
415
431
|
sym_contained = ID2SYM(rb_intern("contained"));
|
416
432
|
sym_use_utf16 = ID2SYM(rb_intern("use_utf16"));
|
433
|
+
sym_message_handler = ID2SYM(rb_intern("message_handler"));
|
417
434
|
/* Intern TinyTds::Error Accessors */
|
418
435
|
intern_source_eql = rb_intern("source=");
|
419
436
|
intern_severity_eql = rb_intern("severity=");
|
@@ -425,6 +442,7 @@ void init_tinytds_client() {
|
|
425
442
|
intern_transpose_iconv_encoding = rb_intern("transpose_iconv_encoding");
|
426
443
|
intern_local_offset = rb_intern("local_offset");
|
427
444
|
intern_gsub = rb_intern("gsub");
|
445
|
+
intern_call = rb_intern("call");
|
428
446
|
/* Escape Regexp Global */
|
429
447
|
opt_escape_regex = rb_funcall(rb_cRegexp, intern_new, 1, rb_str_new2("\\\'"));
|
430
448
|
opt_escape_dblquote = rb_str_new2("''");
|
data/ext/tiny_tds/client.h
CHANGED
@@ -8,6 +8,7 @@ void init_tinytds_client();
|
|
8
8
|
|
9
9
|
typedef struct {
|
10
10
|
short int is_set;
|
11
|
+
int is_message;
|
11
12
|
int cancel;
|
12
13
|
char error[ERROR_MSG_SIZE];
|
13
14
|
char source[ERROR_MSG_SIZE];
|
@@ -38,7 +39,7 @@ typedef struct {
|
|
38
39
|
rb_encoding *encoding;
|
39
40
|
} tinytds_client_wrapper;
|
40
41
|
|
41
|
-
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, const char *error, const char *source, int severity, int dberr, int oserr);
|
42
|
+
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int is_message, int cancel, const char *error, const char *source, int severity, int dberr, int oserr);
|
42
43
|
|
43
44
|
// Lib Macros
|
44
45
|
|
data/ext/tiny_tds/extconsts.rb
CHANGED
@@ -7,9 +7,9 @@ OPENSSL_SOURCE_URI = "https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.
|
|
7
7
|
|
8
8
|
FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "1.00.27"
|
9
9
|
FREETDS_VERSION_INFO = Hash.new { |h,k|
|
10
|
-
h[k] = {files: "
|
10
|
+
h[k] = {files: "http://www.freetds.org/files/stable/freetds-#{k}.tar.bz2"}
|
11
11
|
}
|
12
|
-
FREETDS_VERSION_INFO['1.00'] = {files: '
|
13
|
-
FREETDS_VERSION_INFO['0.99'] = {files: '
|
14
|
-
FREETDS_VERSION_INFO['0.95'] = {files: '
|
12
|
+
FREETDS_VERSION_INFO['1.00'] = {files: 'http://www.freetds.org/files/stable/freetds-1.00.tar.bz2'}
|
13
|
+
FREETDS_VERSION_INFO['0.99'] = {files: 'http://www.freetds.org/files/current/freetds-dev.0.99.678.tar.gz'}
|
14
|
+
FREETDS_VERSION_INFO['0.95'] = {files: 'http://www.freetds.org/files/stable/freetds-0.95.92.tar.gz'}
|
15
15
|
FREETDS_SOURCE_URI = FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
|
data/ext/tiny_tds/result.c
CHANGED
@@ -98,6 +98,7 @@ static void nogvl_cleanup(DBPROCESS *client) {
|
|
98
98
|
if (userdata->nonblocking_error.is_set) {
|
99
99
|
userdata->nonblocking_error.is_set = 0;
|
100
100
|
rb_tinytds_raise_error(client,
|
101
|
+
userdata->nonblocking_error.is_message,
|
101
102
|
userdata->nonblocking_error.cancel,
|
102
103
|
userdata->nonblocking_error.error,
|
103
104
|
userdata->nonblocking_error.source,
|
data/lib/tiny_tds/client.rb
CHANGED
@@ -10,6 +10,7 @@ module TinyTds
|
|
10
10
|
}
|
11
11
|
|
12
12
|
attr_reader :query_options
|
13
|
+
attr_reader :message_handler
|
13
14
|
|
14
15
|
class << self
|
15
16
|
|
@@ -37,6 +38,12 @@ module TinyTds
|
|
37
38
|
if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
|
38
39
|
raise ArgumentError, 'missing :host option if no :dataserver given'
|
39
40
|
end
|
41
|
+
|
42
|
+
@message_handler = opts[:message_handler]
|
43
|
+
if @message_handler && !@message_handler.respond_to?(:call)
|
44
|
+
raise ArgumentError, ':message_handler must implement `call` (eg, a Proc or a Method)'
|
45
|
+
end
|
46
|
+
|
40
47
|
opts[:username] = parse_username(opts)
|
41
48
|
@query_options = self.class.default_query_options.dup
|
42
49
|
opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ''
|
data/test/bin/install-freetds.sh
CHANGED
@@ -7,7 +7,7 @@ if [ -z "$FREETDS_VERSION" ]; then
|
|
7
7
|
FREETDS_VERSION=$(ruby -r "./ext/tiny_tds/extconsts.rb" -e "puts FREETDS_VERSION")
|
8
8
|
fi
|
9
9
|
|
10
|
-
wget
|
10
|
+
wget http://www.freetds.org/files/stable/freetds-$FREETDS_VERSION.tar.gz
|
11
11
|
tar -xzf freetds-$FREETDS_VERSION.tar.gz
|
12
12
|
cd freetds-$FREETDS_VERSION
|
13
13
|
./configure --prefix=/opt/local \
|
data/test/client_test.rb
CHANGED
@@ -59,7 +59,7 @@ class ClientTest < TinyTds::TestCase
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'must be able to use :host/:port connection' do
|
62
|
-
host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST']
|
62
|
+
host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST'] || 'localhost'
|
63
63
|
port = ENV['TINYTDS_UNIT_PORT_TEST'] || ENV['TINYTDS_UNIT_PORT'] || 1433
|
64
64
|
begin
|
65
65
|
client = new_connection dataserver: nil, host: host, port: port
|
data/test/result_test.rb
CHANGED
@@ -614,6 +614,46 @@ class ResultTest < TinyTds::TestCase
|
|
614
614
|
|
615
615
|
if sqlserver?
|
616
616
|
|
617
|
+
describe 'using :message_handler option' do
|
618
|
+
let(:messages) { Array.new }
|
619
|
+
|
620
|
+
before do
|
621
|
+
close_client
|
622
|
+
@client = new_connection message_handler: Proc.new { |m| messages << m }
|
623
|
+
end
|
624
|
+
|
625
|
+
after do
|
626
|
+
messages.clear
|
627
|
+
end
|
628
|
+
|
629
|
+
it 'has a message handler that responds to call' do
|
630
|
+
assert @client.message_handler.respond_to?(:call)
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'calls the provided message handler when severity is 10 or less' do
|
634
|
+
(1..10).to_a.each do |severity|
|
635
|
+
messages.clear
|
636
|
+
msg = "Test #{severity} severity"
|
637
|
+
state = rand(1..255)
|
638
|
+
@client.execute("RAISERROR(N'#{msg}', #{severity}, #{state})").do
|
639
|
+
m = messages.first
|
640
|
+
assert_equal 1, messages.length, 'there should be one message after one raiserror'
|
641
|
+
assert_equal msg, m.message, 'message text'
|
642
|
+
assert_equal severity, m.severity, 'message severity' unless severity == 10 && m.severity.to_i == 0
|
643
|
+
assert_equal state, m.os_error_number, 'message state'
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
it 'calls the provided message handler for `print` messages' do
|
648
|
+
messages.clear
|
649
|
+
msg = 'hello'
|
650
|
+
@client.execute("PRINT '#{msg}'").do
|
651
|
+
m = messages.first
|
652
|
+
assert_equal 1, messages.length, 'there should be one message after one print statement'
|
653
|
+
assert_equal msg, m.message, 'message text'
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
617
657
|
it 'must not raise an error when severity is 10 or less' do
|
618
658
|
(1..10).to_a.each do |severity|
|
619
659
|
@client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
|
data/test/test_helper.rb
CHANGED
@@ -75,8 +75,8 @@ module TinyTds
|
|
75
75
|
username = (sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_USER'] : ENV['TINYTDS_UNIT_USER']) || 'tinytds'
|
76
76
|
password = (sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_PASS'] : ENV['TINYTDS_UNIT_PASS']) || ''
|
77
77
|
{ :dataserver => sqlserver_azure? ? nil : ENV['TINYTDS_UNIT_DATASERVER'],
|
78
|
-
:host => ENV['TINYTDS_UNIT_HOST'],
|
79
|
-
:port => ENV['TINYTDS_UNIT_PORT'],
|
78
|
+
:host => ENV['TINYTDS_UNIT_HOST'] || 'localhost',
|
79
|
+
:port => ENV['TINYTDS_UNIT_PORT'] || '1433',
|
80
80
|
:tds_version => ENV['TINYTDS_UNIT_VERSION'],
|
81
81
|
:username => username,
|
82
82
|
:password => password,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.0.
|
4
|
+
version: 2.1.0.pre4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-09-
|
13
|
+
date: 2017-09-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: mini_portile2
|