tiny_tds 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/CHANGELOG +15 -1
- data/MIT-LICENSE +2 -1
- data/README.md +27 -2
- data/Rakefile +69 -16
- data/compile/rake-compiler-dev-box.patch +31 -0
- data/ext/patch/Makefile.in.diff +29 -0
- data/ext/patch/dblib-30-char-username.diff +11 -0
- data/ext/tiny_tds/client.c +100 -53
- data/ext/tiny_tds/client.h +12 -0
- data/ext/tiny_tds/extconf.rb +11 -2
- data/ext/tiny_tds/result.c +84 -28
- data/lib/tiny_tds/version.rb +1 -1
- data/tasks/ports.rake +52 -44
- data/test/result_test.rb +17 -1
- data/test/thread_test.rb +51 -0
- metadata +29 -53
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Mzk0MTAzZTg1NTc3NTVjODlkZDg1ZmI5YzA1OWFlMzNhOTIzYzBmYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDlkMTUxMjVjNmM0ZjMxMDJmZjE2YmE1MTExYzY1MDA4NDAzZTJhMQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTZkZGQ5ZDg1MzA5YzFiN2QxMmIxOGEyNGZhZmIzODI5YjM5MDA1NGM4Yjhi
|
10
|
+
MGM4MzE0OGZlODE4NzIxZjMzMmE0Njc1ZjBiNzczZDI5MjJmMGMxMzdmODFk
|
11
|
+
NzNkYWJlOGFhMjE0ZGQxYTlmZDExN2UxNTVkMzllNmRkYjAwMjA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YWZjYmU0NzQxYzIxMTlkZjJkNjNkNTYyNzU1NTk3ZjYxNmIyNTI0YzZkZGE0
|
14
|
+
ZmQ1ZGZmZDNmODA0NTFlMDQyZGUxMWFiYjJjNTAzYzMwNWY1ZDhhZWNkNTI5
|
15
|
+
NjY5NGZlYmE5NTFhMTc4NmM5YzJkNDViMjYyNmU4NjYwNTJiMDA=
|
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
|
2
|
+
* 0.6.2 *
|
3
|
+
|
4
|
+
* Support an optional environment variable to find FreeTDS. Fixes #128.
|
5
|
+
|
6
|
+
* Allow Support for 31+ Character Usernames/Passwords. Fixes #134. Thanks @wbond.
|
7
|
+
|
8
|
+
* Stronger Global VM Lock support for nonblocking connections. Fixes #133. Thanks @wbond.
|
9
|
+
|
10
|
+
* Timeout fix for working with Azure SQL. Fixes #138.
|
11
|
+
|
12
|
+
* Correctly handle requests that return multiple results sets via `.do`, such
|
13
|
+
as backups and restores. Fixes #150.
|
14
|
+
|
15
|
+
|
2
16
|
* 0.6.1 *
|
3
17
|
|
4
18
|
Use both dbsetversion() vs. dbsetlversion. Partially reverts #62.
|
@@ -8,7 +22,7 @@ Use both dbsetversion() vs. dbsetlversion. Partially reverts #62.
|
|
8
22
|
|
9
23
|
* Use dbsetversion() vs. dbsetlversion. Fixes #62.
|
10
24
|
|
11
|
-
* Remove Ruby 1.8
|
25
|
+
* Remove Ruby 1.8 support.
|
12
26
|
|
13
27
|
* Implement misc rb_thread_blocking_region support. Fixes #121. Thanks @lepfhty.
|
14
28
|
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
Copyright (c) 2010-
|
1
|
+
Copyright (c) 2010-2014 Ken Collins <ken@metaskills.net>,
|
2
|
+
Will Bond (Veracross LLC) <wbond@breuer.com>
|
2
3
|
|
3
4
|
Permission is hereby granted, free of charge, to any person
|
4
5
|
obtaining a copy of this software and associated documentation
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ The API is simple and consists of these classes:
|
|
13
13
|
|
14
14
|
## Install
|
15
15
|
|
16
|
-
Installing with rubygems should just work. TinyTDS is tested on
|
16
|
+
Installing with rubygems should just work. TinyTDS is currently tested on Ruby version 1.9.3 and upward. Older versions are tested with Ruby 1.8 and lower. If you are using Ruby 1.8, please use v0.6.0.rc1 or lower. The v0.6.0 release and higher are only compatible with Ruby 1.9.3 (or higher).
|
17
17
|
|
18
18
|
```
|
19
19
|
$ gem install tiny_tds
|
@@ -302,6 +302,31 @@ $ rake TINYTDS_FREETDS_VERSION="current"
|
|
302
302
|
To find out more about the FreeTDS release system [visit this thread](http://lists.ibiblio.org/pipermail/freetds/2012q1/027756.html) on their mailing list. You can also browse thier FTP server [ftp://ftp.astron.com/pub/freetds/](ftp://ftp.astron.com/pub/freetds/) for version number strings.
|
303
303
|
|
304
304
|
|
305
|
+
## Compiling Gems for Windows
|
306
|
+
|
307
|
+
For the convenience of Windows users, TinyTDS ships pre-compiled for Ruby 1.9.3, 2.0 and 2.1 on Windows. In order to generate these gems, [rake-compiler-dev-box](https://github.com/tjschuck/rake-compiler-dev-box) is used. This project provides a [Vagrant](http://www.vagrantup.com/) box with rvm, cross-compilers and a number of different versions of ruby.
|
308
|
+
|
309
|
+
There are a handful of rake tasks that are part of TinyTDS that make cross-compiling simple. Ensure that you have VirtualBox, Vagrant and git installed, and then run the following to download the box and perform initial setup:
|
310
|
+
|
311
|
+
```
|
312
|
+
$ rake cross-compile:setup
|
313
|
+
```
|
314
|
+
|
315
|
+
Once the setup is complete, run the following rake task to compile the gem for Windows. The first time this will take a while since the `rake-compiler` gem will need to compile a few different versions of ruby:
|
316
|
+
|
317
|
+
```
|
318
|
+
$ rake cross-compile
|
319
|
+
```
|
320
|
+
|
321
|
+
The compiled gems will exist in `./rake-compile-dev-box/tiny_tds/pkg/`.
|
322
|
+
|
323
|
+
If you want to clean up the dependent ports, temp files and resulting gems, run:
|
324
|
+
|
325
|
+
```
|
326
|
+
$ rake cross-compile:clean
|
327
|
+
```
|
328
|
+
|
329
|
+
|
305
330
|
## Development & Testing
|
306
331
|
|
307
332
|
We use bundler for development. Simply run `bundle install` then `rake` to build the gem and run the unit tests. The tests assume you have created a database named `tinytdstest` accessible by a database owner named `tinytds`. Before running the test rake task, you may need to define a pair of environment variables that help the client connect to your specific FreeTDS database server name and which schema (2000, 2005, 2008, Azure or Sybase ASE) to use. For example:
|
@@ -356,5 +381,5 @@ I am trying to save up for a Happy Hacking pro keyboard. Help me out via GitTip!
|
|
356
381
|
|
357
382
|
## License
|
358
383
|
|
359
|
-
TinyTDS is Copyright (c) 2010-
|
384
|
+
TinyTDS is Copyright (c) 2010-2014 Ken Collins, <ken@metaskills.net> and Will Bond (Veracross LLC) <wbond@breuer.com>. It is distributed under the MIT license. Windows binaries contain precompiled versions of FreeTDS <http://www.freetds.org/> which is licensed under the GNU LGPL license at <http://www.gnu.org/licenses/lgpl-2.0.html>
|
360
385
|
|
data/Rakefile
CHANGED
@@ -6,15 +6,6 @@ require 'rake/testtask'
|
|
6
6
|
require 'rake/extensiontask'
|
7
7
|
require 'rubygems/package_task'
|
8
8
|
|
9
|
-
# My notes for cross compile native Windows gem.
|
10
|
-
#
|
11
|
-
# $ git clean -x -d -f
|
12
|
-
# $ bundle install
|
13
|
-
# $ unalias rake-compiler && unalias rake
|
14
|
-
# $ rake compile
|
15
|
-
# $ rake cross compile RUBY_CC_VERSION=1.9.3
|
16
|
-
# $ rake cross native gem RUBY_CC_VERSION=1.9.3
|
17
|
-
|
18
9
|
def test_libs
|
19
10
|
['lib','test']
|
20
11
|
end
|
@@ -23,9 +14,7 @@ def test_files
|
|
23
14
|
Dir.glob("test/**/*_test.rb").sort
|
24
15
|
end
|
25
16
|
|
26
|
-
|
27
|
-
@clean_gemspec ||= eval(File.read(File.expand_path('../tiny_tds.gemspec', __FILE__)))
|
28
|
-
end
|
17
|
+
gemspec = Gem::Specification::load(File.expand_path('../tiny_tds.gemspec', __FILE__))
|
29
18
|
|
30
19
|
Rake::TestTask.new do |t|
|
31
20
|
t.libs = test_libs
|
@@ -40,6 +29,12 @@ end
|
|
40
29
|
|
41
30
|
task :compile => ["ports:freetds"] unless ENV['TINYTDS_SKIP_PORTS']
|
42
31
|
|
32
|
+
task :build => [:clean, :compile]
|
33
|
+
|
34
|
+
task :default => [:build, :test]
|
35
|
+
|
36
|
+
Dir["tasks/*.rake"].sort.each { |f| load f }
|
37
|
+
|
43
38
|
Rake::ExtensionTask.new('tiny_tds', gemspec) do |ext|
|
44
39
|
ext.lib_dir = 'lib/tiny_tds'
|
45
40
|
if RUBY_PLATFORM =~ /mswin|mingw/ then
|
@@ -48,14 +43,72 @@ Rake::ExtensionTask.new('tiny_tds', gemspec) do |ext|
|
|
48
43
|
ext.lib_dir = "lib/tiny_tds/#{$1}"
|
49
44
|
else
|
50
45
|
ext.cross_compile = true
|
51
|
-
ext.cross_platform = [
|
46
|
+
ext.cross_platform = []
|
52
47
|
ext.cross_config_options << "--disable-lookup"
|
48
|
+
config_opts = {}
|
49
|
+
|
50
|
+
platform_host_map = {
|
51
|
+
'x86-mingw32' => 'i586-mingw32msvc',
|
52
|
+
'x64-mingw32' => 'x86_64-w64-mingw32'
|
53
|
+
}
|
54
|
+
|
55
|
+
# This section ensures we setup up rake dependencies and that libiconv
|
56
|
+
# and freetds are compiled using the cross-compiler and then passed to
|
57
|
+
# extconf.rb in such a way that library detection works.
|
58
|
+
platform_host_map.each do |plat, host|
|
59
|
+
ext.cross_platform << plat
|
60
|
+
|
61
|
+
libiconv = define_libiconv_recipe(plat, host)
|
62
|
+
freetds = define_freetds_recipe(plat, host, libiconv)
|
63
|
+
task "native:#{plat}" => ["ports:freetds:#{plat}"] unless ENV['TINYTDS_SKIP_PORTS']
|
64
|
+
|
65
|
+
# For some reason --with-freetds-dir and --with-iconv-dir would not work.
|
66
|
+
# It seems the default params that extconf.rb constructs include
|
67
|
+
# --without-freetds-include, --without-freetds-lib, --without-iconv-lib
|
68
|
+
# and --without-iconv-include. Thus we must explicitly override them.
|
69
|
+
config_opts[plat] = " --with-freetds-include=#{freetds.path}/include"
|
70
|
+
config_opts[plat] += " --with-freetds-lib=#{freetds.path}/lib"
|
71
|
+
config_opts[plat] += " --with-iconv-include=#{libiconv.path}/include"
|
72
|
+
config_opts[plat] += " --with-iconv-lib=#{libiconv.path}/lib"
|
73
|
+
end
|
74
|
+
|
75
|
+
ext.cross_config_options << config_opts
|
53
76
|
end
|
54
77
|
end
|
55
78
|
|
56
|
-
|
79
|
+
desc "Checks out rake-compiler-dev-box and sets up the cross-compiling box. This can take a long time."
|
80
|
+
task 'cross-compile:setup' do
|
81
|
+
# Make sure we have the command-line programs we need
|
82
|
+
sh 'git', '--version'
|
83
|
+
sh 'vagrant', '-v'
|
57
84
|
|
58
|
-
|
85
|
+
if Dir.exists? 'rake-compiler-dev-box'
|
86
|
+
Dir.chdir 'rake-compiler-dev-box'
|
87
|
+
else
|
88
|
+
sh 'git', 'clone', 'https://github.com/tjschuck/rake-compiler-dev-box.git'
|
89
|
+
Dir.chdir 'rake-compiler-dev-box'
|
90
|
+
sh 'patch -p1 < ../compile/rake-compiler-dev-box.patch'
|
91
|
+
end
|
59
92
|
|
60
|
-
|
93
|
+
sh 'vagrant', 'up'
|
94
|
+
end
|
95
|
+
|
96
|
+
desc "Invokes the cross-compiler to generate gems for windows"
|
97
|
+
task 'cross-compile' do
|
98
|
+
build_dir = './rake-compiler-dev-box/tiny_tds/'
|
99
|
+
if not Dir.exists?(build_dir)
|
100
|
+
Dir.mkdir build_dir
|
101
|
+
end
|
102
|
+
# Copy the current version of tiny_tds into the box directory
|
103
|
+
Dir.entries('./').each do |entry|
|
104
|
+
next if ['.', '..', 'rake-compiler-dev-box'].include?(entry)
|
105
|
+
cp_r entry, build_dir, :remove_destination => true
|
106
|
+
end
|
107
|
+
Dir.chdir './rake-compiler-dev-box'
|
108
|
+
sh 'vagrant ssh -c "package_win32_fat_binary tiny_tds"'
|
109
|
+
end
|
61
110
|
|
111
|
+
desc "Cleans up all of the compiled ports, gems and tmp files from cross-compile"
|
112
|
+
task 'cross-compile:clean' do
|
113
|
+
rm_r './rake-compiler-dev-box/tiny_tds'
|
114
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
diff --git a/bin/package_win32_fat_binary b/bin/package_win32_fat_binary
|
2
|
+
index b336eb7..8ef4f98 100755
|
3
|
+
--- a/bin/package_win32_fat_binary
|
4
|
+
+++ b/bin/package_win32_fat_binary
|
5
|
+
@@ -12,9 +12,8 @@ cd '/vagrant'
|
6
|
+
# passed in path of gem to be cross-compiled
|
7
|
+
cd $1
|
8
|
+
|
9
|
+
-# need to use 1.8.7 for fat-binaries (1.9.3 can't cross-build 1.8.7)
|
10
|
+
-rvm use 1.8.7
|
11
|
+
+rvm use 1.9.3
|
12
|
+
bundle install
|
13
|
+
|
14
|
+
bundle exec rake clean
|
15
|
+
-bundle exec rake cross native gem RUBY_CC_VERSION=1.8.7:1.9.3:2.0.0
|
16
|
+
+bundle exec rake cross native gem RUBY_CC_VERSION=1.9.3:2.0.0:2.1.1
|
17
|
+
diff --git a/bin/prepare_xrubies b/bin/prepare_xrubies
|
18
|
+
index 0e2043c..bd1d3c8 100755
|
19
|
+
--- a/bin/prepare_xrubies
|
20
|
+
+++ b/bin/prepare_xrubies
|
21
|
+
@@ -18,10 +18,6 @@ rvm all do gem install rake-compiler -v "~> 0.9.2"
|
22
|
+
# Use just one CPU for building 1.8.7 and 1.9.3
|
23
|
+
export MAKE="make"
|
24
|
+
|
25
|
+
-# Build 1.8.7 with mingw32 compiler (GCC 4.2)
|
26
|
+
-rvm use 1.8.7
|
27
|
+
-rake-compiler cross-ruby VERSION=1.8.7-p374 HOST=i586-mingw32msvc
|
28
|
+
-
|
29
|
+
# Build 1.9.3 using 1.9.3 as base
|
30
|
+
rvm use 1.9.3
|
31
|
+
rake-compiler cross-ruby VERSION=1.9.3-p545 HOST=i586-mingw32msvc
|
@@ -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
|
+
}
|
data/ext/tiny_tds/client.c
CHANGED
@@ -24,7 +24,7 @@ VALUE opt_escape_regex, opt_escape_dblquote;
|
|
24
24
|
|
25
25
|
// Lib Backend (Helpers)
|
26
26
|
|
27
|
-
|
27
|
+
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *source, int severity, int dberr, int oserr) {
|
28
28
|
GET_CLIENT_USERDATA(dbproc);
|
29
29
|
if (cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
|
30
30
|
userdata->dbsqlok_sent = 1;
|
@@ -48,58 +48,105 @@ static VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error,
|
|
48
48
|
// Lib Backend (Memory Management & Handlers)
|
49
49
|
|
50
50
|
int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) {
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
51
|
+
static char *source = "error";
|
52
|
+
GET_CLIENT_USERDATA(dbproc);
|
53
|
+
|
54
|
+
/* Everything should cancel by default */
|
55
|
+
int return_value = INT_CANCEL;
|
56
|
+
int cancel = 0;
|
57
|
+
|
58
|
+
/* These error codes are documented in include/sybdb.h in FreeTDS */
|
59
|
+
switch(dberr) {
|
60
|
+
|
61
|
+
/* We don't want to raise these as a ruby exception for various reasons */
|
62
|
+
case 100: /* SYBEVERDOWN, indicating the connection can only be v7.1 */
|
63
|
+
case SYBESEOF: /* Usually accompanied by another more useful error */
|
64
|
+
case SYBESMSG: /* Generic "check messages from server" error */
|
65
|
+
case SYBEICONVI: /* Just return ?s to the client, as explained in readme */
|
66
|
+
return return_value;
|
67
|
+
|
68
|
+
case SYBEICONVO:
|
69
|
+
dbfreebuf(dbproc);
|
70
|
+
break;
|
71
|
+
|
72
|
+
case SYBETIME:
|
73
|
+
/*
|
74
|
+
SYBETIME is the only error that can send INT_TIMEOUT or INT_CONTINUE,
|
75
|
+
but we don't ever want to automatically retry. Instead have the app
|
76
|
+
decide what to do. We would use INT_TIMEOUT, however it seems tdserror()
|
77
|
+
in tds/util.c converts INT_TIMEOUT to INT_CONTINUE.
|
78
|
+
*/
|
79
|
+
cancel = 1;
|
80
|
+
break;
|
81
|
+
|
82
|
+
case SYBEWRIT:
|
83
|
+
/* Write errors may happen after we abort a statement */
|
84
|
+
if (userdata && (userdata->dbsqlok_sent || userdata->dbcancel_sent)) {
|
85
|
+
return return_value;
|
86
|
+
}
|
87
|
+
cancel = 1;
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
When in non-blocking mode we need to store the exception data to throw it
|
93
|
+
once the blocking call returns, otherwise we will segfault ruby since part
|
94
|
+
of the contract of the ruby non-blocking indicator is that you do not call
|
95
|
+
any of the ruby C API.
|
96
|
+
*/
|
97
|
+
if (userdata && userdata->nonblocking) {
|
98
|
+
if (cancel && !dbdead(dbproc) && !userdata->closed) {
|
99
|
+
dbcancel(dbproc);
|
100
|
+
userdata->dbcancel_sent = 1;
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
If we've already captured an error message, don't overwrite it. This is
|
105
|
+
here because FreeTDS sends a generic "General SQL Server error" message
|
106
|
+
that will overwrite the real message. This is not normally a problem
|
107
|
+
because a ruby exception is normally thrown and we bail before the
|
108
|
+
generic message can be sent.
|
109
|
+
*/
|
110
|
+
if (!userdata->nonblocking_error.is_set) {
|
111
|
+
userdata->nonblocking_error.cancel = cancel;
|
112
|
+
strcpy(userdata->nonblocking_error.error, dberrstr);
|
113
|
+
strcpy(userdata->nonblocking_error.source, source);
|
114
|
+
userdata->nonblocking_error.severity = severity;
|
115
|
+
userdata->nonblocking_error.dberr = dberr;
|
116
|
+
userdata->nonblocking_error.oserr = oserr;
|
117
|
+
userdata->nonblocking_error.is_set = 1;
|
118
|
+
}
|
119
|
+
|
120
|
+
} else {
|
121
|
+
rb_tinytds_raise_error(dbproc, cancel, dberrstr, source, severity, dberr, oserr);
|
122
|
+
}
|
123
|
+
|
124
|
+
return return_value;
|
97
125
|
}
|
98
126
|
|
99
127
|
int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) {
|
100
128
|
static char *source = "message";
|
101
|
-
|
102
|
-
|
129
|
+
GET_CLIENT_USERDATA(dbproc);
|
130
|
+
if (severity > 10) {
|
131
|
+
// See tinytds_err_handler() for info about why we do this
|
132
|
+
if (userdata && userdata->nonblocking) {
|
133
|
+
if (!userdata->nonblocking_error.is_set) {
|
134
|
+
userdata->nonblocking_error.cancel = 1;
|
135
|
+
strcpy(userdata->nonblocking_error.error, msgtext);
|
136
|
+
strcpy(userdata->nonblocking_error.source, source);
|
137
|
+
userdata->nonblocking_error.severity = severity;
|
138
|
+
userdata->nonblocking_error.dberr = msgno;
|
139
|
+
userdata->nonblocking_error.oserr = msgstate;
|
140
|
+
userdata->nonblocking_error.is_set = 1;
|
141
|
+
}
|
142
|
+
if (!dbdead(dbproc) && !userdata->closed) {
|
143
|
+
dbcancel(dbproc);
|
144
|
+
userdata->dbcancel_sent = 1;
|
145
|
+
}
|
146
|
+
} else {
|
147
|
+
rb_tinytds_raise_error(dbproc, 1, msgtext, source, severity, msgno, msgstate);
|
148
|
+
}
|
149
|
+
}
|
103
150
|
return 0;
|
104
151
|
}
|
105
152
|
|
@@ -108,6 +155,8 @@ static void rb_tinytds_client_reset_userdata(tinytds_client_userdata *userdata)
|
|
108
155
|
userdata->dbsql_sent = 0;
|
109
156
|
userdata->dbsqlok_sent = 0;
|
110
157
|
userdata->dbcancel_sent = 0;
|
158
|
+
userdata->nonblocking = 0;
|
159
|
+
userdata->nonblocking_error.is_set = 0;
|
111
160
|
}
|
112
161
|
|
113
162
|
static void rb_tinytds_client_mark(void *ptr) {
|
@@ -264,14 +313,14 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
264
313
|
dbmsghandle(tinytds_msg_handler);
|
265
314
|
GET_CLIENT_WRAPPER(self);
|
266
315
|
cwrap->login = dblogin();
|
316
|
+
if (!NIL_P(version))
|
317
|
+
dbsetlversion(cwrap->login, NUM2INT(version));
|
267
318
|
if (!NIL_P(user))
|
268
319
|
dbsetluser(cwrap->login, StringValuePtr(user));
|
269
320
|
if (!NIL_P(pass))
|
270
321
|
dbsetlpwd(cwrap->login, StringValuePtr(pass));
|
271
322
|
if (!NIL_P(app))
|
272
323
|
dbsetlapp(cwrap->login, StringValuePtr(app));
|
273
|
-
if (!NIL_P(version))
|
274
|
-
dbsetlversion(cwrap->login, NUM2INT(version));
|
275
324
|
if (!NIL_P(ltimeout))
|
276
325
|
dbsetlogintime(NUM2INT(ltimeout));
|
277
326
|
if (!NIL_P(timeout))
|
@@ -357,5 +406,3 @@ void init_tinytds_client() {
|
|
357
406
|
rb_global_variable(&opt_escape_regex);
|
358
407
|
rb_global_variable(&opt_escape_dblquote);
|
359
408
|
}
|
360
|
-
|
361
|
-
|
data/ext/tiny_tds/client.h
CHANGED
@@ -4,6 +4,16 @@
|
|
4
4
|
|
5
5
|
void init_tinytds_client();
|
6
6
|
|
7
|
+
typedef struct {
|
8
|
+
short int is_set;
|
9
|
+
int cancel;
|
10
|
+
char error[1024];
|
11
|
+
char source[1024];
|
12
|
+
int severity;
|
13
|
+
int dberr;
|
14
|
+
int oserr;
|
15
|
+
} tinytds_errordata;
|
16
|
+
|
7
17
|
typedef struct {
|
8
18
|
short int closed;
|
9
19
|
short int timing_out;
|
@@ -11,6 +21,8 @@ typedef struct {
|
|
11
21
|
short int dbsqlok_sent;
|
12
22
|
RETCODE dbsqlok_retcode;
|
13
23
|
short int dbcancel_sent;
|
24
|
+
short int nonblocking;
|
25
|
+
tinytds_errordata nonblocking_error;
|
14
26
|
} tinytds_client_userdata;
|
15
27
|
|
16
28
|
typedef struct {
|
data/ext/tiny_tds/extconf.rb
CHANGED
@@ -6,8 +6,17 @@ require 'mkmf'
|
|
6
6
|
|
7
7
|
# Shamelessly copied from nokogiri
|
8
8
|
#
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
FREETDSDIR = ENV['FREETDS_DIR']
|
11
|
+
|
12
|
+
if FREETDSDIR.nil? || FREETDSDIR.empty?
|
13
|
+
LIBDIR = RbConfig::CONFIG['libdir']
|
14
|
+
INCLUDEDIR = RbConfig::CONFIG['includedir']
|
15
|
+
else
|
16
|
+
puts "Will use #{FREETDSDIR}"
|
17
|
+
LIBDIR = "#{FREETDSDIR}/lib"
|
18
|
+
INCLUDEDIR = "#{FREETDSDIR}/include"
|
19
|
+
end
|
11
20
|
|
12
21
|
$CFLAGS << " #{ENV["CFLAGS"]}"
|
13
22
|
$LDFLAGS << " #{ENV["LDFLAGS"]}"
|
data/ext/tiny_tds/result.c
CHANGED
@@ -19,7 +19,7 @@ extern VALUE mTinyTds, cTinyTdsClient, cTinyTdsError;
|
|
19
19
|
VALUE cBigDecimal, cDate, cDateTime;
|
20
20
|
VALUE opt_decimal_zero, opt_float_zero, opt_one, opt_zero, opt_four, opt_19hdr, opt_tenk, opt_onemil;
|
21
21
|
int opt_ruby_186;
|
22
|
-
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_merge,
|
22
|
+
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_merge,
|
23
23
|
intern_civil, intern_new_offset, intern_plus, intern_divide, intern_Rational;
|
24
24
|
static ID sym_symbolize_keys, sym_as, sym_array, sym_cache_rows, sym_first, sym_timezone, sym_local, sym_utc, sym_empty_sets;
|
25
25
|
|
@@ -79,35 +79,72 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
|
|
79
79
|
|
80
80
|
#define NOGVL_DBCALL(_dbfunction, _client) ( \
|
81
81
|
(RETCODE)rb_thread_blocking_region( \
|
82
|
-
(rb_blocking_function_t*)
|
82
|
+
(rb_blocking_function_t*)_dbfunction, _client, \
|
83
83
|
(rb_unblock_function_t*)dbcancel_ubf, _client ) \
|
84
84
|
)
|
85
85
|
|
86
|
+
static void dbcancel_ubf(DBPROCESS *client) {
|
87
|
+
GET_CLIENT_USERDATA(client);
|
88
|
+
dbcancel(client);
|
89
|
+
userdata->dbcancel_sent = 1;
|
90
|
+
}
|
91
|
+
|
92
|
+
static void nogvl_setup(DBPROCESS *client) {
|
93
|
+
GET_CLIENT_USERDATA(client);
|
94
|
+
userdata->nonblocking = 1;
|
95
|
+
}
|
96
|
+
|
97
|
+
static void nogvl_cleanup(DBPROCESS *client) {
|
98
|
+
GET_CLIENT_USERDATA(client);
|
99
|
+
userdata->nonblocking = 0;
|
100
|
+
/*
|
101
|
+
Now that the blocking operation is done, we can finally throw any
|
102
|
+
exceptions based on errors from SQL Server.
|
103
|
+
*/
|
104
|
+
if (userdata->nonblocking_error.is_set) {
|
105
|
+
userdata->nonblocking_error.is_set = 0;
|
106
|
+
rb_tinytds_raise_error(client,
|
107
|
+
userdata->nonblocking_error.cancel,
|
108
|
+
&userdata->nonblocking_error.error,
|
109
|
+
&userdata->nonblocking_error.source,
|
110
|
+
userdata->nonblocking_error.severity,
|
111
|
+
userdata->nonblocking_error.dberr,
|
112
|
+
userdata->nonblocking_error.oserr);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
86
116
|
static RETCODE nogvl_dbsqlok(DBPROCESS *client) {
|
87
117
|
int retcode = FAIL;
|
88
118
|
GET_CLIENT_USERDATA(client);
|
89
|
-
|
119
|
+
nogvl_setup(client);
|
120
|
+
retcode = NOGVL_DBCALL(dbsqlok, client);
|
121
|
+
nogvl_cleanup(client);
|
90
122
|
userdata->dbsqlok_sent = 1;
|
91
123
|
return retcode;
|
92
124
|
}
|
93
125
|
|
94
126
|
static RETCODE nogvl_dbsqlexec(DBPROCESS *client) {
|
95
|
-
|
127
|
+
int retcode = FAIL;
|
128
|
+
nogvl_setup(client);
|
129
|
+
retcode = NOGVL_DBCALL(dbsqlexec, client);
|
130
|
+
nogvl_cleanup(client);
|
131
|
+
return retcode;
|
96
132
|
}
|
97
133
|
|
98
134
|
static RETCODE nogvl_dbresults(DBPROCESS *client) {
|
99
|
-
|
135
|
+
int retcode = FAIL;
|
136
|
+
nogvl_setup(client);
|
137
|
+
retcode = NOGVL_DBCALL(dbresults, client);
|
138
|
+
nogvl_cleanup(client);
|
139
|
+
return retcode;
|
100
140
|
}
|
101
141
|
|
102
142
|
static RETCODE nogvl_dbnextrow(DBPROCESS * client) {
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
dbcancel(client);
|
109
|
-
userdata->dbcancel_sent = 1;
|
110
|
-
userdata->dbsql_sent = 0;
|
143
|
+
int retcode = FAIL;
|
144
|
+
nogvl_setup(client);
|
145
|
+
retcode = NOGVL_DBCALL(dbnextrow, client);
|
146
|
+
nogvl_cleanup(client);
|
147
|
+
return retcode;
|
111
148
|
}
|
112
149
|
|
113
150
|
// Lib Backend (Helpers)
|
@@ -118,7 +155,7 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
|
|
118
155
|
RETCODE db_rc;
|
119
156
|
ruby_rc = rb_ary_entry(rwrap->dbresults_retcodes, rwrap->number_of_results);
|
120
157
|
if (NIL_P(ruby_rc)) {
|
121
|
-
db_rc =
|
158
|
+
db_rc = nogvl_dbresults(rwrap->client);
|
122
159
|
ruby_rc = INT2FIX(db_rc);
|
123
160
|
rb_ary_store(rwrap->dbresults_retcodes, rwrap->number_of_results, ruby_rc);
|
124
161
|
} else {
|
@@ -130,14 +167,29 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
|
|
130
167
|
static RETCODE rb_tinytds_result_ok_helper(DBPROCESS *client) {
|
131
168
|
GET_CLIENT_USERDATA(client);
|
132
169
|
if (userdata->dbsqlok_sent == 0) {
|
133
|
-
userdata->dbsqlok_retcode =
|
170
|
+
userdata->dbsqlok_retcode = nogvl_dbsqlok(client);
|
134
171
|
}
|
135
172
|
return userdata->dbsqlok_retcode;
|
136
173
|
}
|
137
174
|
|
138
|
-
static void
|
175
|
+
static void rb_tinytds_result_exec_helper(DBPROCESS *client) {
|
139
176
|
GET_CLIENT_USERDATA(client);
|
140
|
-
rb_tinytds_result_ok_helper(client);
|
177
|
+
RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(client);
|
178
|
+
if (dbsqlok_rc == SUCCEED) {
|
179
|
+
/*
|
180
|
+
This is to just process each result set. Commands such as backup and
|
181
|
+
restore are not done when the first result set is returned, so we need to
|
182
|
+
exhaust the result sets before it is complete.
|
183
|
+
*/
|
184
|
+
while (nogvl_dbresults(client) == SUCCEED) {
|
185
|
+
/*
|
186
|
+
If we don't loop through each row for calls to TinyTds::Result.do that
|
187
|
+
actually do return result sets, we will trigger error 20019 about trying
|
188
|
+
to execute a new command with pending results. Oh well.
|
189
|
+
*/
|
190
|
+
while (dbnextrow(client) != NO_MORE_ROWS);
|
191
|
+
}
|
192
|
+
}
|
141
193
|
dbcancel(client);
|
142
194
|
userdata->dbcancel_sent = 1;
|
143
195
|
userdata->dbsql_sent = 0;
|
@@ -175,7 +227,7 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
175
227
|
val = *(int *)data ? Qtrue : Qfalse;
|
176
228
|
break;
|
177
229
|
case SYBNUMERIC:
|
178
|
-
case SYBDECIMAL: {
|
230
|
+
case SYBDECIMAL: {
|
179
231
|
DBTYPEINFO *data_info = dbcoltypeinfo(rwrap->client, col);
|
180
232
|
int data_slength = (int)data_info->precision + (int)data_info->scale + 1;
|
181
233
|
char converted_decimal[data_slength];
|
@@ -373,7 +425,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
373
425
|
/* Create rows for this result set. */
|
374
426
|
unsigned long rowi = 0;
|
375
427
|
VALUE result = rb_ary_new();
|
376
|
-
while (
|
428
|
+
while (nogvl_dbnextrow(rwrap->client) != NO_MORE_ROWS) {
|
377
429
|
VALUE row = rb_tinytds_result_fetch_row(self, timezone, symbolize_keys, as_array);
|
378
430
|
if (cache_rows)
|
379
431
|
rb_ary_store(result, rowi, row);
|
@@ -404,9 +456,9 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
404
456
|
dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
|
405
457
|
rb_ary_store(rwrap->fields_processed, rwrap->number_of_results, Qnil);
|
406
458
|
} else {
|
407
|
-
// If we do not find results, side step the rb_tinytds_result_dbresults_retcode helper and
|
459
|
+
// If we do not find results, side step the rb_tinytds_result_dbresults_retcode helper and
|
408
460
|
// manually populate its memoized array while nullifing any memoized fields too before loop.
|
409
|
-
dbresults_rc =
|
461
|
+
dbresults_rc = nogvl_dbresults(rwrap->client);
|
410
462
|
rb_ary_store(rwrap->dbresults_retcodes, rwrap->number_of_results, INT2FIX(dbresults_rc));
|
411
463
|
rb_ary_store(rwrap->fields_processed, rwrap->number_of_results, Qnil);
|
412
464
|
}
|
@@ -426,15 +478,19 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
426
478
|
static VALUE rb_tinytds_result_cancel(VALUE self) {
|
427
479
|
GET_RESULT_WRAPPER(self);
|
428
480
|
GET_CLIENT_USERDATA(rwrap->client);
|
429
|
-
if (rwrap->client && !userdata->dbcancel_sent)
|
430
|
-
|
481
|
+
if (rwrap->client && !userdata->dbcancel_sent) {
|
482
|
+
RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
|
483
|
+
dbcancel(rwrap->client);
|
484
|
+
userdata->dbcancel_sent = 1;
|
485
|
+
userdata->dbsql_sent = 0;
|
486
|
+
}
|
431
487
|
return Qtrue;
|
432
488
|
}
|
433
489
|
|
434
490
|
static VALUE rb_tinytds_result_do(VALUE self) {
|
435
491
|
GET_RESULT_WRAPPER(self);
|
436
492
|
if (rwrap->client) {
|
437
|
-
|
493
|
+
rb_tinytds_result_exec_helper(rwrap->client);
|
438
494
|
return LONG2NUM((long)dbcount(rwrap->client));
|
439
495
|
} else {
|
440
496
|
return Qnil;
|
@@ -463,13 +519,13 @@ static VALUE rb_tinytds_result_return_code(VALUE self) {
|
|
463
519
|
static VALUE rb_tinytds_result_insert(VALUE self) {
|
464
520
|
GET_RESULT_WRAPPER(self);
|
465
521
|
if (rwrap->client) {
|
466
|
-
|
522
|
+
rb_tinytds_result_exec_helper(rwrap->client);
|
467
523
|
VALUE identity = Qnil;
|
468
524
|
dbcmd(rwrap->client, rwrap->cwrap->identity_insert_sql);
|
469
|
-
if (
|
470
|
-
&&
|
525
|
+
if (nogvl_dbsqlexec(rwrap->client) != FAIL
|
526
|
+
&& nogvl_dbresults(rwrap->client) != FAIL
|
471
527
|
&& DBROWS(rwrap->client) != FAIL) {
|
472
|
-
while (
|
528
|
+
while (nogvl_dbnextrow(rwrap->client) != NO_MORE_ROWS) {
|
473
529
|
int col = 1;
|
474
530
|
BYTE *data = dbdata(rwrap->client, col);
|
475
531
|
DBINT data_len = dbdatlen(rwrap->client, col);
|
data/lib/tiny_tds/version.rb
CHANGED
data/tasks/ports.rake
CHANGED
@@ -1,71 +1,79 @@
|
|
1
1
|
require 'mini_portile'
|
2
|
-
require 'rake/extensioncompiler'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"current" => {:files => "ftp://ftp.astron.com/pub/freetds/current/freetds-current.tgz"}
|
16
|
-
})
|
3
|
+
# If your using 0.82, you may have to make a conf file to get it to work. For example:
|
4
|
+
# $ export FREETDSCONF='/opt/local/etc/freetds/freetds.conf'
|
5
|
+
ICONV_VERSION = "1.14"
|
6
|
+
FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "0.91"
|
7
|
+
FREETDS_VERSION_INFO = Hash.new { |h,k|
|
8
|
+
h[k] = {:files => "ftp://ftp.astron.com/pub/freetds/stable/freetds-#{k}.tar.gz"}
|
9
|
+
}.merge({
|
10
|
+
"0.82" => {:files => "ftp://ftp.astron.com/pub/freetds/old/0.82/freetds-0.82.tar.gz"},
|
11
|
+
"0.91" => {:files => "ftp://ftp.astron.com/pub/freetds/stable/freetds-0.91.tar.gz"},
|
12
|
+
"current" => {:files => "ftp://ftp.astron.com/pub/freetds/current/freetds-current.tgz"}
|
13
|
+
})
|
17
14
|
|
18
|
-
|
15
|
+
# all ports depends on this directory to exist
|
16
|
+
directory "ports"
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def define_libiconv_recipe(platform, host)
|
19
|
+
recipe = MiniPortile.new "libiconv", ICONV_VERSION
|
20
|
+
recipe.files << "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
|
21
|
+
recipe.host = host
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
if FREETDS_VERSION == "0.91"
|
28
|
-
$recipes[:freetds].patch_files << File.expand_path(File.join('..', '..', 'ext', 'patch', 'sspi_w_kerberos.diff'), __FILE__)
|
29
|
-
end
|
30
|
-
end
|
23
|
+
desc "Compile libiconv for '#{platform}' (#{host})"
|
24
|
+
task "ports:libiconv:#{platform}" => ["ports"] do
|
25
|
+
checkpoint = "ports/.#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
|
31
26
|
|
32
|
-
desc "Compile libiconv support library"
|
33
|
-
task :libiconv => ["ports"] do
|
34
|
-
recipe = $recipes[:libiconv]
|
35
|
-
checkpoint = "ports/.#{recipe.name}.#{recipe.version}.#{recipe.host}.timestamp"
|
36
27
|
unless File.exist?(checkpoint)
|
28
|
+
# always produce position independent code
|
37
29
|
recipe.configure_options << "CFLAGS='-fPIC'"
|
38
30
|
recipe.cook
|
39
31
|
touch checkpoint
|
40
32
|
end
|
41
|
-
recipe.activate
|
42
33
|
end
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
35
|
+
recipe
|
36
|
+
end
|
37
|
+
|
38
|
+
def define_freetds_recipe(platform, host, libiconv)
|
39
|
+
recipe = MiniPortile.new "freetds", FREETDS_VERSION
|
40
|
+
recipe.files << FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
|
41
|
+
recipe.host = host
|
42
|
+
|
43
|
+
if recipe.respond_to?(:patch_files) && FREETDS_VERSION == "0.91"
|
44
|
+
recipe.patch_files << File.expand_path(File.join('..', '..', 'ext', 'patch', 'sspi_w_kerberos.diff'), __FILE__)
|
45
|
+
recipe.patch_files << File.expand_path(File.join('..', '..', 'ext', 'patch', 'dblib-30-char-username.diff'), __FILE__)
|
46
|
+
unless RUBY_PLATFORM =~ /mswin|mingw/
|
47
|
+
recipe.patch_files << File.expand_path(File.join('..', '..', 'ext', 'patch', 'Makefile.in.diff'), __FILE__)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Compile freetds for '#{platform}' (#{host})"
|
52
|
+
task "ports:freetds:#{platform}" => ["ports", "ports:libiconv:#{platform}"] do
|
53
|
+
checkpoint = "ports/.#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
|
54
|
+
|
48
55
|
unless File.exist?(checkpoint)
|
49
56
|
with_tdsver = ENV['TINYTDS_FREETDS_VERSION'] =~ /0\.8/ ? "--with-tdsver=8.0" : "--with-tdsver=7.1"
|
50
57
|
for_windows = recipe.host =~ /mswin|mingw/i
|
58
|
+
recipe.configure_options << '--with-pic'
|
59
|
+
recipe.configure_options << "--with-libiconv-prefix=#{libiconv.path}"
|
51
60
|
recipe.configure_options << '--sysconfdir="C:/Sites"' if for_windows
|
52
61
|
recipe.configure_options << '--enable-sspi' if for_windows
|
53
62
|
recipe.configure_options << "--disable-odbc"
|
54
63
|
recipe.configure_options << with_tdsver
|
55
|
-
recipe.configure_options << "CFLAGS='-fPIC'"
|
56
64
|
recipe.cook
|
57
65
|
touch checkpoint
|
58
66
|
end
|
59
|
-
recipe.activate
|
60
67
|
end
|
61
68
|
|
69
|
+
recipe
|
62
70
|
end
|
63
71
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
+
# native compilation of ports
|
73
|
+
host = RbConfig::CONFIG["host"]
|
74
|
+
libiconv = define_libiconv_recipe(RUBY_PLATFORM, host)
|
75
|
+
freetds = define_freetds_recipe(RUBY_PLATFORM, host, libiconv)
|
76
|
+
|
77
|
+
# compile native FreeTDS
|
78
|
+
desc "Compile native freetds"
|
79
|
+
task "ports:freetds" => ["ports:freetds:#{RUBY_PLATFORM}"]
|
data/test/result_test.rb
CHANGED
@@ -549,7 +549,23 @@ class ResultTest < TinyTds::TestCase
|
|
549
549
|
end
|
550
550
|
|
551
551
|
end
|
552
|
-
|
552
|
+
|
553
|
+
describe 'Complex query with multiple results sets but no actual results' do
|
554
|
+
it 'must not cancel the query until complete' do
|
555
|
+
@client.execute("
|
556
|
+
BACKUP DATABASE tinytdstest
|
557
|
+
TO DISK = 'C:\\Users\\Public\\tinytdstest.bak'
|
558
|
+
").do
|
559
|
+
end
|
560
|
+
|
561
|
+
after do
|
562
|
+
begin
|
563
|
+
File.delete 'C:\\Users\\Public\\tinytdstest.bak'
|
564
|
+
rescue
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
553
569
|
describe 'when casting to native ruby values' do
|
554
570
|
|
555
571
|
it 'returns fixnum for 1' do
|
data/test/thread_test.rb
CHANGED
@@ -38,6 +38,57 @@ class ThreadTest < TinyTds::TestCase
|
|
38
38
|
assert x > mintime, "#{x} is not slower than #{mintime} seconds"
|
39
39
|
end
|
40
40
|
|
41
|
+
it 'should not crash on error in parallel' do
|
42
|
+
threads = []
|
43
|
+
@numthreads.times do |i|
|
44
|
+
threads << Thread.new do
|
45
|
+
@pool.with do |client|
|
46
|
+
begin
|
47
|
+
result = client.execute "select dbname()"
|
48
|
+
result.each { |r| puts r }
|
49
|
+
rescue Exception => e
|
50
|
+
# We are throwing an error on purpose here since 0.6.1 would
|
51
|
+
# segfault on errors thrown in threads
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
threads.each { |t| t.join }
|
57
|
+
assert true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should cancel when hitting timeout in thread' do
|
61
|
+
exception = false
|
62
|
+
|
63
|
+
thread = Thread.new do
|
64
|
+
@pool.with do |client|
|
65
|
+
begin
|
66
|
+
# The default query timeout is 5, so this will last longer than that
|
67
|
+
result = client.execute "waitfor delay '00:00:07'; select db_name()"
|
68
|
+
result.each { |r| puts r }
|
69
|
+
rescue TinyTds::Error => e
|
70
|
+
if e.message == 'Adaptive Server connection timed out'
|
71
|
+
exception = true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
timer_thread = Thread.new do
|
78
|
+
# Sleep until after the timeout (of 5) should have been reached
|
79
|
+
sleep(6)
|
80
|
+
if not exception
|
81
|
+
thread.kill
|
82
|
+
raise "Timeout passed without query timing out"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
thread.join
|
87
|
+
timer_thread.join
|
88
|
+
|
89
|
+
assert exception
|
90
|
+
end
|
91
|
+
|
41
92
|
end
|
42
93
|
|
43
94
|
end
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.6.1
|
4
|
+
version: 0.6.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ken Collins
|
9
8
|
- Erik Bryn
|
9
|
+
- Will Bond
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -19,47 +19,41 @@ dependencies:
|
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 0.9.2
|
22
|
-
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
23
24
|
version_requirements: !ruby/object:Gem::Requirement
|
24
25
|
requirements:
|
25
26
|
- - ~>
|
26
27
|
- !ruby/object:Gem::Version
|
27
28
|
version: 0.9.2
|
28
|
-
none: false
|
29
|
-
prerelease: false
|
30
|
-
type: :development
|
31
29
|
- !ruby/object:Gem::Dependency
|
32
30
|
name: mini_portile
|
33
31
|
requirement: !ruby/object:Gem::Requirement
|
34
32
|
requirements:
|
35
33
|
- - ~>
|
36
34
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.5.
|
38
|
-
|
35
|
+
version: 0.5.1
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
39
38
|
version_requirements: !ruby/object:Gem::Requirement
|
40
39
|
requirements:
|
41
40
|
- - ~>
|
42
41
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.5.
|
44
|
-
none: false
|
45
|
-
prerelease: false
|
46
|
-
type: :development
|
42
|
+
version: 0.5.1
|
47
43
|
- !ruby/object:Gem::Dependency
|
48
44
|
name: rake-compiler
|
49
45
|
requirement: !ruby/object:Gem::Requirement
|
50
46
|
requirements:
|
51
|
-
- -
|
47
|
+
- - ~>
|
52
48
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.
|
54
|
-
|
49
|
+
version: 0.9.1
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
55
52
|
version_requirements: !ruby/object:Gem::Requirement
|
56
53
|
requirements:
|
57
|
-
- -
|
54
|
+
- - ~>
|
58
55
|
- !ruby/object:Gem::Version
|
59
|
-
version: 0.
|
60
|
-
none: false
|
61
|
-
prerelease: false
|
62
|
-
type: :development
|
56
|
+
version: 0.9.1
|
63
57
|
- !ruby/object:Gem::Dependency
|
64
58
|
name: activesupport
|
65
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,15 +61,13 @@ dependencies:
|
|
67
61
|
- - ~>
|
68
62
|
- !ruby/object:Gem::Version
|
69
63
|
version: '3.0'
|
70
|
-
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
71
66
|
version_requirements: !ruby/object:Gem::Requirement
|
72
67
|
requirements:
|
73
68
|
- - ~>
|
74
69
|
- !ruby/object:Gem::Version
|
75
70
|
version: '3.0'
|
76
|
-
none: false
|
77
|
-
prerelease: false
|
78
|
-
type: :development
|
79
71
|
- !ruby/object:Gem::Dependency
|
80
72
|
name: minitest
|
81
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,15 +75,13 @@ dependencies:
|
|
83
75
|
- - ! '>='
|
84
76
|
- !ruby/object:Gem::Version
|
85
77
|
version: '0'
|
86
|
-
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
87
80
|
version_requirements: !ruby/object:Gem::Requirement
|
88
81
|
requirements:
|
89
82
|
- - ! '>='
|
90
83
|
- !ruby/object:Gem::Version
|
91
84
|
version: '0'
|
92
|
-
none: false
|
93
|
-
prerelease: false
|
94
|
-
type: :development
|
95
85
|
- !ruby/object:Gem::Dependency
|
96
86
|
name: connection_pool
|
97
87
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,19 +89,18 @@ dependencies:
|
|
99
89
|
- - ~>
|
100
90
|
- !ruby/object:Gem::Version
|
101
91
|
version: 0.9.2
|
102
|
-
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
103
94
|
version_requirements: !ruby/object:Gem::Requirement
|
104
95
|
requirements:
|
105
96
|
- - ~>
|
106
97
|
- !ruby/object:Gem::Version
|
107
98
|
version: 0.9.2
|
108
|
-
none: false
|
109
|
-
prerelease: false
|
110
|
-
type: :development
|
111
99
|
description: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
112
100
|
Developed for the ActiveRecord SQL Server adapter.
|
113
101
|
email:
|
114
102
|
- ken@metaskills.net
|
103
|
+
- will@wbond.net
|
115
104
|
executables: []
|
116
105
|
extensions:
|
117
106
|
- ext/tiny_tds/extconf.rb
|
@@ -123,6 +112,9 @@ files:
|
|
123
112
|
- MIT-LICENSE
|
124
113
|
- README.md
|
125
114
|
- Rakefile
|
115
|
+
- compile/rake-compiler-dev-box.patch
|
116
|
+
- ext/patch/Makefile.in.diff
|
117
|
+
- ext/patch/dblib-30-char-username.diff
|
126
118
|
- ext/patch/sspi_w_kerberos.diff
|
127
119
|
- ext/tiny_tds/client.c
|
128
120
|
- ext/tiny_tds/client.h
|
@@ -153,6 +145,7 @@ files:
|
|
153
145
|
- test/thread_test.rb
|
154
146
|
homepage: http://github.com/rails-sqlserver/tiny_tds
|
155
147
|
licenses: []
|
148
|
+
metadata: {}
|
156
149
|
post_install_message:
|
157
150
|
rdoc_options:
|
158
151
|
- --charset=UTF-8
|
@@ -163,32 +156,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
156
|
- - ! '>='
|
164
157
|
- !ruby/object:Gem::Version
|
165
158
|
version: '0'
|
166
|
-
none: false
|
167
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
160
|
requirements:
|
169
161
|
- - ! '>='
|
170
162
|
- !ruby/object:Gem::Version
|
171
163
|
version: '0'
|
172
|
-
none: false
|
173
164
|
requirements: []
|
174
165
|
rubyforge_project:
|
175
|
-
rubygems_version:
|
166
|
+
rubygems_version: 2.2.2
|
176
167
|
signing_key:
|
177
|
-
specification_version:
|
168
|
+
specification_version: 4
|
178
169
|
summary: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
179
|
-
test_files:
|
180
|
-
- test/benchmark/query.rb
|
181
|
-
- test/benchmark/query_odbc.rb
|
182
|
-
- test/benchmark/query_tinytds.rb
|
183
|
-
- test/client_test.rb
|
184
|
-
- test/result_test.rb
|
185
|
-
- test/schema/1px.gif
|
186
|
-
- test/schema/sqlserver_2000.sql
|
187
|
-
- test/schema/sqlserver_2005.sql
|
188
|
-
- test/schema/sqlserver_2008.sql
|
189
|
-
- test/schema/sqlserver_azure.sql
|
190
|
-
- test/schema/sybase_ase.sql
|
191
|
-
- test/schema_test.rb
|
192
|
-
- test/test_helper.rb
|
193
|
-
- test/thread_test.rb
|
194
|
-
has_rdoc:
|
170
|
+
test_files: []
|