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.
@@ -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
@@ -16,3 +16,4 @@ Gemfile.lock
16
16
  misc
17
17
  *.gem
18
18
  ports
19
+ rake-compiler-dev-box/
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 and 32-bit support.
25
+ * Remove Ruby 1.8 support.
12
26
 
13
27
  * Implement misc rb_thread_blocking_region support. Fixes #121. Thanks @lepfhty.
14
28
 
@@ -1,4 +1,5 @@
1
- Copyright (c) 2010-2011 Ken Collins, <ken@metaskills.net>
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 ruby version 1.9 and upward. Older versions are tested with 1.8.x. We also test everynow and then on JRuby and RBX.
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-2011 Ken Collins, <ken@metaskills.net> and 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>
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
- def gemspec
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 = ['i386-mingw32']
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
- task :build => [:clean, :compile]
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
- task :default => [:build, :test]
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
- Dir["tasks/*.rake"].sort.each { |f| load f }
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
+ }
@@ -24,7 +24,7 @@ VALUE opt_escape_regex, opt_escape_dblquote;
24
24
 
25
25
  // Lib Backend (Helpers)
26
26
 
27
- static VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *source, int severity, int dberr, int oserr) {
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
- static char *source = "error";
52
- GET_CLIENT_USERDATA(dbproc);
53
- int return_value = INT_CONTINUE;
54
- int cancel = 0;
55
- switch(dberr) {
56
- case 100: /* SYBEVERDOWN */
57
- return INT_CANCEL;
58
- case SYBESMSG:
59
- return return_value;
60
- case SYBEICONVO:
61
- dbfreebuf(dbproc);
62
- break;
63
- case SYBEICONVI:
64
- return INT_CANCEL;
65
- case SYBEFCON:
66
- case SYBESOCK:
67
- case SYBECONN:
68
- case SYBEREAD:
69
- return_value = INT_EXIT;
70
- break;
71
- case SYBESEOF: {
72
- if (userdata && userdata->timing_out)
73
- return_value = INT_TIMEOUT;
74
- return INT_CANCEL;
75
- break;
76
- }
77
- case SYBETIME: {
78
- if (userdata) {
79
- if (userdata->timing_out) {
80
- return INT_CONTINUE;
81
- } else {
82
- userdata->timing_out = 1;
83
- }
84
- }
85
- cancel = 1;
86
- break;
87
- }
88
- case SYBEWRIT: {
89
- if (userdata && (userdata->dbsqlok_sent || userdata->dbcancel_sent))
90
- return INT_CANCEL;
91
- cancel = 1;
92
- break;
93
- }
94
- }
95
- rb_tinytds_raise_error(dbproc, cancel, dberrstr, source, severity, dberr, oserr);
96
- return return_value;
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
- if (severity > 10)
102
- rb_tinytds_raise_error(dbproc, 1, msgtext, source, severity, msgno, msgstate);
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
-
@@ -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 {
@@ -6,8 +6,17 @@ require 'mkmf'
6
6
 
7
7
  # Shamelessly copied from nokogiri
8
8
  #
9
- LIBDIR = RbConfig::CONFIG['libdir']
10
- INCLUDEDIR = RbConfig::CONFIG['includedir']
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"]}"
@@ -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*)nogvl_ ## _dbfunction, _client, \
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
- retcode = dbsqlok(client);
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
- return dbsqlexec(client);
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
- return dbresults(client);
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
- return dbnextrow(client);
104
- }
105
-
106
- static void dbcancel_ubf(DBPROCESS *client) {
107
- GET_CLIENT_USERDATA(client);
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 = NOGVL_DBCALL(dbresults, rwrap->client);
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 = NOGVL_DBCALL(dbsqlok, client);
170
+ userdata->dbsqlok_retcode = nogvl_dbsqlok(client);
134
171
  }
135
172
  return userdata->dbsqlok_retcode;
136
173
  }
137
174
 
138
- static void rb_tinytds_result_cancel_helper(DBPROCESS *client) {
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 (NOGVL_DBCALL(dbnextrow, rwrap->client) != NO_MORE_ROWS) {
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 = NOGVL_DBCALL(dbresults, rwrap->client);
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
- rb_tinytds_result_cancel_helper(rwrap->client);
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
- rb_tinytds_result_cancel_helper(rwrap->client);
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
- rb_tinytds_result_cancel_helper(rwrap->client);
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 (NOGVL_DBCALL(dbsqlexec, rwrap->client) != FAIL
470
- && NOGVL_DBCALL(dbresults, rwrap->client) != FAIL
525
+ if (nogvl_dbsqlexec(rwrap->client) != FAIL
526
+ && nogvl_dbresults(rwrap->client) != FAIL
471
527
  && DBROWS(rwrap->client) != FAIL) {
472
- while (NOGVL_DBCALL(dbnextrow, rwrap->client) != NO_MORE_ROWS) {
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);
@@ -1,3 +1,3 @@
1
1
  module TinyTds
2
- VERSION = '0.6.1'
2
+ VERSION = '0.6.2'
3
3
  end
@@ -1,71 +1,79 @@
1
1
  require 'mini_portile'
2
- require 'rake/extensioncompiler'
3
2
 
4
- namespace :ports do
5
-
6
- # If your using 0.82, you may have to make a conf file to get it to work. For example:
7
- # $ export FREETDSCONF='/opt/local/etc/freetds/freetds.conf'
8
- ICONV_VERSION = "1.13.1"
9
- FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "0.91"
10
- FREETDS_VERSION_INFO = Hash.new { |h,k|
11
- h[k] = {:files => "ftp://ftp.astron.com/pub/freetds/stable/freetds-#{k}.tar.gz"}
12
- }.merge({
13
- "0.82" => {:files => "ftp://ftp.astron.com/pub/freetds/old/0.82/freetds-0.82.tar.gz"},
14
- "0.91" => {:files => "ftp://ftp.astron.com/pub/freetds/stable/freetds-0.91.tar.gz"},
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
- directory "ports"
15
+ # all ports depends on this directory to exist
16
+ directory "ports"
19
17
 
20
- $recipes = {}
21
- $recipes[:libiconv] = MiniPortile.new "libiconv", ICONV_VERSION
22
- $recipes[:libiconv].files << "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
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
- $recipes[:freetds] = MiniPortile.new "freetds", FREETDS_VERSION
25
- $recipes[:freetds].files << FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
26
- if $recipes[:freetds].respond_to?(:patch_files)
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
- desc "Compile freetds library"
45
- task :freetds => ["ports", :libiconv] do
46
- recipe = $recipes[:freetds]
47
- checkpoint = "ports/.#{recipe.name}.#{recipe.version}.#{recipe.host}.timestamp"
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
- task :cross do
65
- host = ENV.fetch("HOST", Rake::ExtensionCompiler.mingw_host)
66
- $recipes.each do |_, recipe|
67
- recipe.host = host
68
- end
69
- # hook compile task with dependencies
70
- Rake::Task["compile"].prerequisites.unshift "ports:freetds"
71
- end
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}"]
@@ -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
@@ -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
- prerelease:
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: 2013-07-10 00:00:00.000000000 Z
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
- none: false
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.0
38
- none: false
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.0
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.8.1
54
- none: false
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.8.1
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
- none: false
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
- none: false
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
- none: false
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: 1.8.25
166
+ rubygems_version: 2.2.2
176
167
  signing_key:
177
- specification_version: 3
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: []