tiny_tds 0.6.0.rc1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Gemfile +1 -4
- data/README.md +7 -7
- data/Rakefile +2 -3
- data/ext/tiny_tds/client.c +8 -21
- data/ext/tiny_tds/client.h +1 -3
- data/ext/tiny_tds/result.c +56 -57
- data/ext/tiny_tds/result.h +1 -3
- data/ext/tiny_tds/tiny_tds_ext.h +1 -4
- data/lib/tiny_tds/client.rb +19 -12
- data/lib/tiny_tds/version.rb +1 -1
- data/tasks/ports.rake +5 -1
- data/test/client_test.rb +3 -3
- data/test/result_test.rb +9 -0
- data/test/schema_test.rb +57 -119
- data/test/test_helper.rb +6 -33
- data/test/thread_test.rb +44 -0
- metadata +98 -99
- data/NOTES +0 -11
data/CHANGELOG
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
|
2
2
|
* 0.6.0 *
|
3
3
|
|
4
|
+
* Use dbsetversion() vs. dbsetlversion. Fixes #62.
|
5
|
+
|
6
|
+
* Remove Ruby 1.8 and 32-bit support.
|
7
|
+
|
8
|
+
* Implement misc rb_thread_blocking_region support. Fixes #121. Thanks @lepfhty.
|
9
|
+
|
10
|
+
* Test FreeTDS v0.91.89 patch release.
|
11
|
+
|
12
|
+
* Fix lost connection handling. Fixes #124. Thanks @krzcho.
|
13
|
+
|
14
|
+
* Remove unused variable. Fixes #103. Thanks @jeremyevans.
|
15
|
+
|
4
16
|
* Remove need to specify username for Windows Authentication.
|
5
17
|
|
6
18
|
* Use proper SQL for returning IDENTITY with Sybase. Fixes #95.
|
data/Gemfile
CHANGED
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.
|
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.
|
17
17
|
|
18
18
|
```
|
19
19
|
$ gem install tiny_tds
|
@@ -66,7 +66,7 @@ Creating a new client takes a hash of options. For valid iconv encoding options,
|
|
66
66
|
* :port - Defaults to 1433. Only used if :host is used.
|
67
67
|
* :database - The default database to use.
|
68
68
|
* :appname - Short string seen in SQL Servers process/activity window.
|
69
|
-
* :tds_version - TDS version. Defaults to 71 (7.1) and is not recommended to change!
|
69
|
+
* :tds_version - TDS version. Defaults to "71" (7.1) and is not recommended to change!
|
70
70
|
* :login_timeout - Seconds to wait for login. Default to 60 seconds.
|
71
71
|
* :timeout - Seconds to wait for a response to a SQL command. Default 5 seconds.
|
72
72
|
* :encoding - Any valid iconv value like CP1251 or ISO-8859-1. Default UTF-8.
|
@@ -111,7 +111,6 @@ result.each do |row|
|
|
111
111
|
# By default each row is a hash.
|
112
112
|
# The keys are the fields, as you'd expect.
|
113
113
|
# The values are pre-built ruby primitives mapped from their corresponding types.
|
114
|
-
# Here's an leemer: http://is.gd/g61xo
|
115
114
|
end
|
116
115
|
```
|
117
116
|
|
@@ -161,7 +160,7 @@ result.insert # => 420
|
|
161
160
|
The result object can handle multiple result sets form batched SQL or stored procedures. It is critical to remember that when calling each with a block for the first time will return each "row" of each result set. Calling each a second time with a block will yield each "set".
|
162
161
|
|
163
162
|
```ruby
|
164
|
-
sql = ["SELECT TOP (1) [id] FROM [datatypes]",
|
163
|
+
sql = ["SELECT TOP (1) [id] FROM [datatypes]",
|
165
164
|
"SELECT TOP (2) [bigint] FROM [datatypes] WHERE [bigint] IS NOT NULL"].join(' ')
|
166
165
|
|
167
166
|
set1, set2 = client.execute(sql).each
|
@@ -215,6 +214,7 @@ It is possible to get the return code after executing a stored procedure from ei
|
|
215
214
|
client.return_code # => nil
|
216
215
|
|
217
216
|
result = client.execute("EXEC tinytds_TestReturnCodes")
|
217
|
+
result.do
|
218
218
|
result.return_code # => 420
|
219
219
|
client.return_code # => 420
|
220
220
|
```
|
@@ -278,7 +278,7 @@ MiniPortile is a minimalistic, simplistic and stupid implementation of a port/re
|
|
278
278
|
|
279
279
|
The TinyTDS project uses MiniPortile so that we can easily install a local "project specific" version of FreeTDS and supporting libraries to link against when building a test version of TinyTDS. MiniPortile is a great tool that even allows us to build statically linked components that TinyTDS relies on. Hence this allows us to publish native gems for any platform. We use this feature for gems targeted at Windows.
|
280
280
|
|
281
|
-
You too can use MiniPortile to build TinyTDS and build your own gems for your own package management needs. Here is a few simple steps that assume you have cloned a fresh copy of this repository. 1) Bundling will install all the development dependencies. 2) Running `rake compile` will basically download and install a supported version of FreeTDS in our `ports.rake` file and supporting libraries. These will all be installed into the projects tmp directory. 3) The final `rake native gem` command will build a native gem for your specific platform. 4) The native gem can be found in the `pkg` directory. The last command assumes "X" is version numbers and #{platform} will be your platform.
|
281
|
+
You too can use MiniPortile to build TinyTDS and build your own gems for your own package management needs. Here is a few simple steps that assume you have cloned a fresh copy of this repository. 1) Bundling will install all the development dependencies. 2) Running `rake compile` will basically download and install a supported version of FreeTDS in our `ports.rake` file and supporting libraries. These will all be installed into the projects tmp directory. 3) The final `rake native gem` command will build a native gem for your specific platform. 4) The native gem can be found in the `pkg` directory. The last command assumes "X" is version numbers and #{platform} will be your platform. Note that if you're using Windows make sure you are running these rake tasks with a Unix-style command line tool like [MSYS](http://www.mingw.org/wiki/MSYS).
|
282
282
|
|
283
283
|
```
|
284
284
|
$ bundle install
|
@@ -294,7 +294,7 @@ It is also possible to build a specific version of FreeTDS for your own gem or d
|
|
294
294
|
```
|
295
295
|
$ rake TINYTDS_FREETDS_VERSION="0.82"
|
296
296
|
$ rake TINYTDS_FREETDS_VERSION="0.91"
|
297
|
-
$ rake TINYTDS_FREETDS_VERSION="0.91.
|
297
|
+
$ rake TINYTDS_FREETDS_VERSION="0.91.89"
|
298
298
|
$ rake TINYTDS_FREETDS_VERSION="0.92.405"
|
299
299
|
$ rake TINYTDS_FREETDS_VERSION="current"
|
300
300
|
```
|
@@ -302,7 +302,7 @@ $ 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
|
-
## Development & Testing
|
305
|
+
## Development & Testing
|
306
306
|
|
307
307
|
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:
|
308
308
|
|
data/Rakefile
CHANGED
@@ -8,13 +8,12 @@ require 'rubygems/package_task'
|
|
8
8
|
|
9
9
|
# My notes for cross compile native Windows gem.
|
10
10
|
#
|
11
|
-
# $ rbenv shell 1.8.7
|
12
11
|
# $ git clean -x -d -f
|
13
12
|
# $ bundle install
|
14
13
|
# $ unalias rake-compiler && unalias rake
|
15
14
|
# $ rake compile
|
16
|
-
# $ rake cross compile RUBY_CC_VERSION=1.
|
17
|
-
# $ rake cross native gem RUBY_CC_VERSION=1.
|
15
|
+
# $ rake cross compile RUBY_CC_VERSION=1.9.3
|
16
|
+
# $ rake cross native gem RUBY_CC_VERSION=1.9.3
|
18
17
|
|
19
18
|
def test_libs
|
20
19
|
['lib','test']
|
data/ext/tiny_tds/client.c
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
#include <tiny_tds_ext.h>
|
3
2
|
#include <errno.h>
|
4
3
|
|
@@ -66,6 +65,7 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
66
65
|
case SYBEFCON:
|
67
66
|
case SYBESOCK:
|
68
67
|
case SYBECONN:
|
68
|
+
case SYBEREAD:
|
69
69
|
return_value = INT_EXIT;
|
70
70
|
break;
|
71
71
|
case SYBESEOF: {
|
@@ -91,9 +91,6 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
91
91
|
cancel = 1;
|
92
92
|
break;
|
93
93
|
}
|
94
|
-
case SYBEREAD:
|
95
|
-
cancel = 1;
|
96
|
-
break;
|
97
94
|
}
|
98
95
|
rb_tinytds_raise_error(dbproc, cancel, dberrstr, source, severity, dberr, oserr);
|
99
96
|
return return_value;
|
@@ -197,9 +194,7 @@ static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
|
|
197
194
|
rb_iv_set(result, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), intern_dup, 0));
|
198
195
|
GET_RESULT_WRAPPER(result);
|
199
196
|
rwrap->local_offset = rb_funcall(cTinyTdsClient, intern_local_offset, 0);
|
200
|
-
|
201
|
-
rwrap->encoding = cwrap->encoding;
|
202
|
-
#endif
|
197
|
+
rwrap->encoding = cwrap->encoding;
|
203
198
|
return result;
|
204
199
|
}
|
205
200
|
|
@@ -210,20 +205,14 @@ static VALUE rb_tinytds_charset(VALUE self) {
|
|
210
205
|
|
211
206
|
static VALUE rb_tinytds_encoding(VALUE self) {
|
212
207
|
GET_CLIENT_WRAPPER(self);
|
213
|
-
|
214
|
-
return rb_enc_from_encoding(cwrap->encoding);
|
215
|
-
#else
|
216
|
-
return Qnil;
|
217
|
-
#endif
|
208
|
+
return rb_enc_from_encoding(cwrap->encoding);
|
218
209
|
}
|
219
210
|
|
220
211
|
static VALUE rb_tinytds_escape(VALUE self, VALUE string) {
|
221
212
|
Check_Type(string, T_STRING);
|
222
213
|
GET_CLIENT_WRAPPER(self);
|
223
214
|
VALUE new_string = rb_funcall(string, intern_gsub, 2, opt_escape_regex, opt_escape_dblquote);
|
224
|
-
|
225
|
-
rb_enc_associate(new_string, cwrap->encoding);
|
226
|
-
#endif
|
215
|
+
rb_enc_associate(new_string, cwrap->encoding);
|
227
216
|
return new_string;
|
228
217
|
}
|
229
218
|
|
@@ -281,8 +270,6 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
281
270
|
dbsetlpwd(cwrap->login, StringValuePtr(pass));
|
282
271
|
if (!NIL_P(app))
|
283
272
|
dbsetlapp(cwrap->login, StringValuePtr(app));
|
284
|
-
if (!NIL_P(version))
|
285
|
-
dbsetlversion(cwrap->login, NUM2INT(version));
|
286
273
|
if (!NIL_P(ltimeout))
|
287
274
|
dbsetlogintime(NUM2INT(ltimeout));
|
288
275
|
if (!NIL_P(timeout))
|
@@ -300,15 +287,15 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
300
287
|
if (cwrap->client) {
|
301
288
|
cwrap->closed = 0;
|
302
289
|
cwrap->charset = charset;
|
290
|
+
if (!NIL_P(version))
|
291
|
+
dbsetversion(NUM2INT(version));
|
303
292
|
dbsetuserdata(cwrap->client, (BYTE*)cwrap->userdata);
|
304
293
|
cwrap->userdata->closed = 0;
|
305
294
|
if (!NIL_P(database) && (azure != Qtrue)) {
|
306
295
|
dbuse(cwrap->client, StringValuePtr(database));
|
307
296
|
}
|
308
|
-
|
309
|
-
|
310
|
-
cwrap->encoding = rb_enc_find(StringValuePtr(transposed_encoding));
|
311
|
-
#endif
|
297
|
+
VALUE transposed_encoding = rb_funcall(cTinyTdsClient, intern_transpose_iconv_encoding, 1, charset);
|
298
|
+
cwrap->encoding = rb_enc_find(StringValuePtr(transposed_encoding));
|
312
299
|
if (dbtds(cwrap->client) <= 7) {
|
313
300
|
cwrap->identity_insert_sql = "SELECT CAST(@@IDENTITY AS bigint) AS Ident";
|
314
301
|
} else {
|
data/ext/tiny_tds/client.h
CHANGED
data/ext/tiny_tds/result.c
CHANGED
@@ -4,39 +4,12 @@
|
|
4
4
|
|
5
5
|
// TINY_TDS_MAX_TIME
|
6
6
|
|
7
|
-
#
|
8
|
-
/* On 64bit platforms we can handle dates way outside 2038-01-19T03:14:07 */
|
9
|
-
/* (10000*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59 */
|
10
|
-
#define TINY_TDS_MAX_TIME 315607276799ULL
|
11
|
-
#else
|
12
|
-
/* On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07 */
|
13
|
-
/* 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds */
|
14
|
-
/* (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7 */
|
15
|
-
#define TINY_TDS_MAX_TIME 64318634047ULL
|
16
|
-
#endif
|
7
|
+
#define TINY_TDS_MAX_TIME 315607276799ULL
|
17
8
|
|
18
9
|
|
19
10
|
// TINY_TDS_MIN_TIME
|
20
11
|
|
21
|
-
#
|
22
|
-
/* Ruby 1.9 */
|
23
|
-
/* 0000-1-1 00:00:00 UTC */
|
24
|
-
/* (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0 */
|
25
|
-
#define TINY_TDS_MIN_TIME 2678400ULL
|
26
|
-
#elif SIZEOF_INT < SIZEOF_LONG
|
27
|
-
/* 64bit Ruby 1.8 */
|
28
|
-
/* 0139-1-1 00:00:00 UTC */
|
29
|
-
/* (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0 */
|
30
|
-
#define TINY_TDS_MIN_TIME 4389184800ULL
|
31
|
-
#elif defined(NEGATIVE_TIME_T)
|
32
|
-
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
|
33
|
-
/* (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52 */
|
34
|
-
#define TINY_TDS_MIN_TIME 60023299552ULL
|
35
|
-
#else
|
36
|
-
/* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t. */
|
37
|
-
/* (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1 */
|
38
|
-
#define TINY_TDS_MIN_TIME 62171150401ULL
|
39
|
-
#endif
|
12
|
+
#define TINY_TDS_MIN_TIME 2678400ULL
|
40
13
|
|
41
14
|
|
42
15
|
// File Types/Vars
|
@@ -53,24 +26,17 @@ static ID sym_symbolize_keys, sym_as, sym_array, sym_cache_rows, sym_first, sym_
|
|
53
26
|
|
54
27
|
// Lib Macros
|
55
28
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
})
|
68
|
-
#else
|
69
|
-
#define ENCODED_STR_NEW(_data, _len) \
|
70
|
-
rb_str_new((char *)_data, (long)_len)
|
71
|
-
#define ENCODED_STR_NEW2(_data2) \
|
72
|
-
rb_str_new2((char *)_data2)
|
73
|
-
#endif
|
29
|
+
rb_encoding *binaryEncoding;
|
30
|
+
#define ENCODED_STR_NEW(_data, _len) ({ \
|
31
|
+
VALUE _val = rb_str_new((char *)_data, (long)_len); \
|
32
|
+
rb_enc_associate(_val, rwrap->encoding); \
|
33
|
+
_val; \
|
34
|
+
})
|
35
|
+
#define ENCODED_STR_NEW2(_data2) ({ \
|
36
|
+
VALUE _val = rb_str_new2((char *)_data2); \
|
37
|
+
rb_enc_associate(_val, rwrap->encoding); \
|
38
|
+
_val; \
|
39
|
+
})
|
74
40
|
|
75
41
|
|
76
42
|
// Lib Backend (Memory Management)
|
@@ -109,6 +75,40 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
|
|
109
75
|
return obj;
|
110
76
|
}
|
111
77
|
|
78
|
+
// No GVL Helpers
|
79
|
+
|
80
|
+
#define NOGVL_DBCALL(_dbfunction, _client) ( \
|
81
|
+
(RETCODE)rb_thread_blocking_region( \
|
82
|
+
(rb_blocking_function_t*)nogvl_ ## _dbfunction, _client, \
|
83
|
+
(rb_unblock_function_t*)dbcancel_ubf, _client ) \
|
84
|
+
)
|
85
|
+
|
86
|
+
static RETCODE nogvl_dbsqlok(DBPROCESS *client) {
|
87
|
+
int retcode = FAIL;
|
88
|
+
GET_CLIENT_USERDATA(client);
|
89
|
+
retcode = dbsqlok(client);
|
90
|
+
userdata->dbsqlok_sent = 1;
|
91
|
+
return retcode;
|
92
|
+
}
|
93
|
+
|
94
|
+
static RETCODE nogvl_dbsqlexec(DBPROCESS *client) {
|
95
|
+
return dbsqlexec(client);
|
96
|
+
}
|
97
|
+
|
98
|
+
static RETCODE nogvl_dbresults(DBPROCESS *client) {
|
99
|
+
return dbresults(client);
|
100
|
+
}
|
101
|
+
|
102
|
+
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;
|
111
|
+
}
|
112
112
|
|
113
113
|
// Lib Backend (Helpers)
|
114
114
|
|
@@ -118,7 +118,7 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
|
|
118
118
|
RETCODE db_rc;
|
119
119
|
ruby_rc = rb_ary_entry(rwrap->dbresults_retcodes, rwrap->number_of_results);
|
120
120
|
if (NIL_P(ruby_rc)) {
|
121
|
-
db_rc = dbresults
|
121
|
+
db_rc = NOGVL_DBCALL(dbresults, rwrap->client);
|
122
122
|
ruby_rc = INT2FIX(db_rc);
|
123
123
|
rb_ary_store(rwrap->dbresults_retcodes, rwrap->number_of_results, ruby_rc);
|
124
124
|
} else {
|
@@ -130,8 +130,7 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
|
|
130
130
|
static RETCODE rb_tinytds_result_ok_helper(DBPROCESS *client) {
|
131
131
|
GET_CLIENT_USERDATA(client);
|
132
132
|
if (userdata->dbsqlok_sent == 0) {
|
133
|
-
userdata->dbsqlok_retcode = dbsqlok
|
134
|
-
userdata->dbsqlok_sent = 1;
|
133
|
+
userdata->dbsqlok_retcode = NOGVL_DBCALL(dbsqlok, client);
|
135
134
|
}
|
136
135
|
return userdata->dbsqlok_retcode;
|
137
136
|
}
|
@@ -298,12 +297,10 @@ static VALUE rb_tinytds_result_fields(VALUE self) {
|
|
298
297
|
VALUE fields_processed = rb_ary_entry(rwrap->fields_processed, rwrap->number_of_results);
|
299
298
|
if ((dbsqlok_rc == SUCCEED) && (dbresults_rc == SUCCEED) && (fields_processed == Qnil)) {
|
300
299
|
/* Default query options. */
|
301
|
-
int symbolize_keys = 0
|
300
|
+
int symbolize_keys = 0;
|
302
301
|
VALUE qopts = rb_iv_get(self, "@query_options");
|
303
302
|
if (rb_hash_aref(qopts, sym_symbolize_keys) == Qtrue)
|
304
303
|
symbolize_keys = 1;
|
305
|
-
if (rb_hash_aref(qopts, sym_empty_sets) == Qfalse)
|
306
|
-
empty_sets = 0;
|
307
304
|
/* Set number_of_fields count for this result set. */
|
308
305
|
rwrap->number_of_fields = dbnumcols(rwrap->client);
|
309
306
|
if (rwrap->number_of_fields > 0) {
|
@@ -376,7 +373,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
376
373
|
/* Create rows for this result set. */
|
377
374
|
unsigned long rowi = 0;
|
378
375
|
VALUE result = rb_ary_new();
|
379
|
-
while (dbnextrow
|
376
|
+
while (NOGVL_DBCALL(dbnextrow, rwrap->client) != NO_MORE_ROWS) {
|
380
377
|
VALUE row = rb_tinytds_result_fetch_row(self, timezone, symbolize_keys, as_array);
|
381
378
|
if (cache_rows)
|
382
379
|
rb_ary_store(result, rowi, row);
|
@@ -409,7 +406,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
409
406
|
} else {
|
410
407
|
// If we do not find results, side step the rb_tinytds_result_dbresults_retcode helper and
|
411
408
|
// manually populate its memoized array while nullifing any memoized fields too before loop.
|
412
|
-
dbresults_rc = dbresults
|
409
|
+
dbresults_rc = NOGVL_DBCALL(dbresults, rwrap->client);
|
413
410
|
rb_ary_store(rwrap->dbresults_retcodes, rwrap->number_of_results, INT2FIX(dbresults_rc));
|
414
411
|
rb_ary_store(rwrap->fields_processed, rwrap->number_of_results, Qnil);
|
415
412
|
}
|
@@ -469,8 +466,10 @@ static VALUE rb_tinytds_result_insert(VALUE self) {
|
|
469
466
|
rb_tinytds_result_cancel_helper(rwrap->client);
|
470
467
|
VALUE identity = Qnil;
|
471
468
|
dbcmd(rwrap->client, rwrap->cwrap->identity_insert_sql);
|
472
|
-
if (dbsqlexec
|
473
|
-
|
469
|
+
if (NOGVL_DBCALL(dbsqlexec, rwrap->client) != FAIL
|
470
|
+
&& NOGVL_DBCALL(dbresults, rwrap->client) != FAIL
|
471
|
+
&& DBROWS(rwrap->client) != FAIL) {
|
472
|
+
while (NOGVL_DBCALL(dbnextrow, rwrap->client) != NO_MORE_ROWS) {
|
474
473
|
int col = 1;
|
475
474
|
BYTE *data = dbdata(rwrap->client, col);
|
476
475
|
DBINT data_len = dbdatlen(rwrap->client, col);
|
data/ext/tiny_tds/result.h
CHANGED
@@ -16,9 +16,7 @@ typedef struct {
|
|
16
16
|
VALUE fields;
|
17
17
|
VALUE fields_processed;
|
18
18
|
VALUE results;
|
19
|
-
|
20
|
-
rb_encoding *encoding;
|
21
|
-
#endif
|
19
|
+
rb_encoding *encoding;
|
22
20
|
VALUE dbresults_retcodes;
|
23
21
|
unsigned int number_of_results;
|
24
22
|
unsigned int number_of_fields;
|
data/ext/tiny_tds/tiny_tds_ext.h
CHANGED
data/lib/tiny_tds/client.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module TinyTds
|
2
2
|
class Client
|
3
3
|
|
4
|
+
# From sybdb.h comments:
|
5
|
+
# DBVERSION_xxx are used with dbsetversion()
|
6
|
+
#
|
4
7
|
TDS_VERSIONS_SETTERS = {
|
5
8
|
'unknown' => 0,
|
6
9
|
'46' => 1,
|
@@ -12,19 +15,23 @@ module TinyTds
|
|
12
15
|
'72' => 6,
|
13
16
|
'90' => 6
|
14
17
|
}.freeze
|
15
|
-
|
18
|
+
|
19
|
+
# From sybdb.h comments:
|
20
|
+
# DBTDS_xxx are returned by DBTDS()
|
21
|
+
# The integer values of the constants are poorly chosen.
|
22
|
+
#
|
16
23
|
TDS_VERSIONS_GETTERS = {
|
17
|
-
0 => {:name => 'DBTDS_UNKNOWN',
|
18
|
-
1 => {:name => 'DBTDS_2_0',
|
19
|
-
2 => {:name => 'DBTDS_3_4',
|
20
|
-
3 => {:name => 'DBTDS_4_0',
|
21
|
-
4 => {:name => 'DBTDS_4_2',
|
22
|
-
5 => {:name => 'DBTDS_4_6',
|
23
|
-
6 => {:name => 'DBTDS_4_9_5',
|
24
|
-
7 => {:name => 'DBTDS_5_0',
|
25
|
-
8 => {:name => 'DBTDS_7_0',
|
26
|
-
9 => {:name => 'DBTDS_7_1',
|
27
|
-
10 => {:name => 'DBTDS_7_2',
|
24
|
+
0 => {:name => 'DBTDS_UNKNOWN', :description => 'Unknown'},
|
25
|
+
1 => {:name => 'DBTDS_2_0', :description => 'Pre 4.0 SQL Server'},
|
26
|
+
2 => {:name => 'DBTDS_3_4', :description => 'Microsoft SQL Server (3.0)'},
|
27
|
+
3 => {:name => 'DBTDS_4_0', :description => '4.0 SQL Server'},
|
28
|
+
4 => {:name => 'DBTDS_4_2', :description => '4.2 SQL Server'},
|
29
|
+
5 => {:name => 'DBTDS_4_6', :description => '2.0 OpenServer and 4.6 SQL Server.'},
|
30
|
+
6 => {:name => 'DBTDS_4_9_5', :description => '4.9.5 (NCR) SQL Server'},
|
31
|
+
7 => {:name => 'DBTDS_5_0', :description => '5.0 SQL Server'},
|
32
|
+
8 => {:name => 'DBTDS_7_0', :description => 'Microsoft SQL Server 7.0'},
|
33
|
+
9 => {:name => 'DBTDS_7_1/DBTDS_8_0', :description => 'Microsoft SQL Server 2000'},
|
34
|
+
10 => {:name => 'DBTDS_7_2/DBTDS_9_0', :description => 'Microsoft SQL Server 2005'}
|
28
35
|
}.freeze
|
29
36
|
|
30
37
|
@@default_query_options = {
|
data/lib/tiny_tds/version.rb
CHANGED
data/tasks/ports.rake
CHANGED
@@ -23,7 +23,11 @@ namespace :ports do
|
|
23
23
|
|
24
24
|
$recipes[:freetds] = MiniPortile.new "freetds", FREETDS_VERSION
|
25
25
|
$recipes[:freetds].files << FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
|
26
|
-
|
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
|
27
31
|
|
28
32
|
desc "Compile libiconv support library"
|
29
33
|
task :libiconv => ["ports"] do
|
data/test/client_test.rb
CHANGED
@@ -30,13 +30,13 @@ class ClientTest < TinyTds::TestCase
|
|
30
30
|
assert_equal 'DBTDS_5_0 - 5.0 SQL Server', @client.tds_version_info
|
31
31
|
else
|
32
32
|
assert_equal 9, @client.tds_version
|
33
|
-
assert_equal 'DBTDS_7_1 - Microsoft SQL Server 2000', @client.tds_version_info
|
33
|
+
assert_equal 'DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000', @client.tds_version_info
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'uses UTF-8 client charset/encoding by default' do
|
38
38
|
assert_equal 'UTF-8', @client.charset
|
39
|
-
assert_equal Encoding.find('UTF-8'), @client.encoding
|
39
|
+
assert_equal Encoding.find('UTF-8'), @client.encoding
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'has a #escape method used for quote strings' do
|
@@ -47,7 +47,7 @@ class ClientTest < TinyTds::TestCase
|
|
47
47
|
['CP850', 'CP1252', 'ISO-8859-1'].each do |encoding|
|
48
48
|
client = new_connection(:encoding => encoding)
|
49
49
|
assert_equal encoding, client.charset
|
50
|
-
assert_equal Encoding.find(encoding), client.encoding
|
50
|
+
assert_equal Encoding.find(encoding), client.encoding
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
data/test/result_test.rb
CHANGED
@@ -74,6 +74,15 @@ class ResultTest < TinyTds::TestCase
|
|
74
74
|
assert_instance_of Array, row
|
75
75
|
assert_equal [:one], result.fields
|
76
76
|
end
|
77
|
+
|
78
|
+
it 'allows sql concat + to work' do
|
79
|
+
rollback_transaction(@client) do
|
80
|
+
@client.execute("DELETE FROM [datatypes]").do
|
81
|
+
@client.execute("INSERT INTO [datatypes] ([char_10], [varchar_50]) VALUES ('1', '2')").do
|
82
|
+
result = @client.execute("SELECT TOP (1) [char_10] + 'test' + [varchar_50] AS [test] FROM [datatypes]").each.first['test']
|
83
|
+
result.must_equal "1 test2"
|
84
|
+
end
|
85
|
+
end
|
77
86
|
|
78
87
|
it 'must be able to turn :cache_rows option off' do
|
79
88
|
result = @client.execute(@query1)
|
data/test/schema_test.rb
CHANGED
@@ -8,7 +8,7 @@ class SchemaTest < TinyTds::TestCase
|
|
8
8
|
before do
|
9
9
|
@@current_schema_loaded ||= load_current_schema
|
10
10
|
@client = new_connection
|
11
|
-
@gif1px =
|
11
|
+
@gif1px = File.read('test/schema/1px.gif',:mode=>"rb:BINARY")
|
12
12
|
end
|
13
13
|
|
14
14
|
describe 'for shared types' do
|
@@ -39,77 +39,40 @@ class SchemaTest < TinyTds::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'casts datetime' do
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
assert_equal 0, find_value(63, :datetime, :timezone => :utc).utc_offset
|
77
|
-
else
|
78
|
-
# 1753-01-01T00:00:00.000
|
79
|
-
v = find_value 61, :datetime
|
80
|
-
assert_instance_of Time, v, 'not in range of Time class'
|
81
|
-
assert_equal 1753, v.year
|
82
|
-
assert_equal 01, v.month
|
83
|
-
assert_equal 01, v.day
|
84
|
-
assert_equal 0, v.hour
|
85
|
-
assert_equal 0, v.min
|
86
|
-
assert_equal 0, v.sec
|
87
|
-
assert_equal 0, v.usec
|
88
|
-
# 9999-12-31T23:59:59.997
|
89
|
-
v = find_value 62, :datetime
|
90
|
-
assert_instance_of Time, v, 'not in range of Time class'
|
91
|
-
assert_equal 9999, v.year
|
92
|
-
assert_equal 12, v.month
|
93
|
-
assert_equal 31, v.day
|
94
|
-
assert_equal 23, v.hour
|
95
|
-
assert_equal 59, v.min
|
96
|
-
assert_equal 59, v.sec
|
97
|
-
assert_equal 997000, v.usec unless ruby186?
|
98
|
-
assert_equal utc_offset, find_value(62, :datetime, :timezone => :local).utc_offset
|
99
|
-
assert_equal 0, find_value(62, :datetime, :timezone => :utc).utc_offset
|
100
|
-
# 2010-01-01T12:34:56.123
|
101
|
-
v = find_value 63, :datetime
|
102
|
-
assert_instance_of Time, v, 'in range of Time class'
|
103
|
-
assert_equal 2010, v.year
|
104
|
-
assert_equal 01, v.month
|
105
|
-
assert_equal 01, v.day
|
106
|
-
assert_equal 12, v.hour
|
107
|
-
assert_equal 34, v.min
|
108
|
-
assert_equal 56, v.sec
|
109
|
-
assert_equal 123000, v.usec
|
110
|
-
assert_equal utc_offset, find_value(63, :datetime, :timezone => :local).utc_offset
|
111
|
-
assert_equal 0, find_value(63, :datetime, :timezone => :utc).utc_offset
|
112
|
-
end
|
42
|
+
# 1753-01-01T00:00:00.000
|
43
|
+
v = find_value 61, :datetime
|
44
|
+
assert_instance_of Time, v, 'not in range of Time class'
|
45
|
+
assert_equal 1753, v.year
|
46
|
+
assert_equal 01, v.month
|
47
|
+
assert_equal 01, v.day
|
48
|
+
assert_equal 0, v.hour
|
49
|
+
assert_equal 0, v.min
|
50
|
+
assert_equal 0, v.sec
|
51
|
+
assert_equal 0, v.usec
|
52
|
+
# 9999-12-31T23:59:59.997
|
53
|
+
v = find_value 62, :datetime
|
54
|
+
assert_instance_of Time, v, 'not in range of Time class'
|
55
|
+
assert_equal 9999, v.year
|
56
|
+
assert_equal 12, v.month
|
57
|
+
assert_equal 31, v.day
|
58
|
+
assert_equal 23, v.hour
|
59
|
+
assert_equal 59, v.min
|
60
|
+
assert_equal 59, v.sec
|
61
|
+
assert_equal 997000, v.usec
|
62
|
+
assert_equal utc_offset, find_value(62, :datetime, :timezone => :local).utc_offset
|
63
|
+
assert_equal 0, find_value(62, :datetime, :timezone => :utc).utc_offset
|
64
|
+
# 2010-01-01T12:34:56.123
|
65
|
+
v = find_value 63, :datetime
|
66
|
+
assert_instance_of Time, v, 'in range of Time class'
|
67
|
+
assert_equal 2010, v.year
|
68
|
+
assert_equal 01, v.month
|
69
|
+
assert_equal 01, v.day
|
70
|
+
assert_equal 12, v.hour
|
71
|
+
assert_equal 34, v.min
|
72
|
+
assert_equal 56, v.sec
|
73
|
+
assert_equal 123000, v.usec
|
74
|
+
assert_equal utc_offset, find_value(63, :datetime, :timezone => :local).utc_offset
|
75
|
+
assert_equal 0, find_value(63, :datetime, :timezone => :utc).utc_offset
|
113
76
|
end
|
114
77
|
|
115
78
|
it 'casts decimal' do
|
@@ -183,53 +146,28 @@ class SchemaTest < TinyTds::TestCase
|
|
183
146
|
end
|
184
147
|
|
185
148
|
it 'casts smalldatetime' do
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
assert_equal 0, find_value(232, :smalldatetime, :timezone => :utc).offset
|
209
|
-
else
|
210
|
-
# 1901-01-01 15:45:00
|
211
|
-
v = find_value 231, :smalldatetime
|
212
|
-
assert_instance_of Time, v
|
213
|
-
assert_equal 1901, v.year
|
214
|
-
assert_equal 01, v.month
|
215
|
-
assert_equal 01, v.day
|
216
|
-
assert_equal 15, v.hour
|
217
|
-
assert_equal 45, v.min
|
218
|
-
assert_equal 00, v.sec
|
219
|
-
assert_equal Time.local(1901).utc_offset, find_value(231, :smalldatetime, :timezone => :local).utc_offset
|
220
|
-
assert_equal 0, find_value(231, :smalldatetime, :timezone => :utc).utc_offset
|
221
|
-
# 2078-06-05 04:20:00
|
222
|
-
v = find_value 232, :smalldatetime
|
223
|
-
assert_instance_of Time, v
|
224
|
-
assert_equal 2078, v.year
|
225
|
-
assert_equal 06, v.month
|
226
|
-
assert_equal 05, v.day
|
227
|
-
assert_equal 04, v.hour
|
228
|
-
assert_equal 20, v.min
|
229
|
-
assert_equal 00, v.sec
|
230
|
-
assert_equal Time.local(2078,6).utc_offset, find_value(232, :smalldatetime, :timezone => :local).utc_offset
|
231
|
-
assert_equal 0, find_value(232, :smalldatetime, :timezone => :utc).utc_offset
|
232
|
-
end
|
149
|
+
# 1901-01-01 15:45:00
|
150
|
+
v = find_value 231, :smalldatetime
|
151
|
+
assert_instance_of Time, v
|
152
|
+
assert_equal 1901, v.year
|
153
|
+
assert_equal 01, v.month
|
154
|
+
assert_equal 01, v.day
|
155
|
+
assert_equal 15, v.hour
|
156
|
+
assert_equal 45, v.min
|
157
|
+
assert_equal 00, v.sec
|
158
|
+
assert_equal Time.local(1901).utc_offset, find_value(231, :smalldatetime, :timezone => :local).utc_offset
|
159
|
+
assert_equal 0, find_value(231, :smalldatetime, :timezone => :utc).utc_offset
|
160
|
+
# 2078-06-05 04:20:00
|
161
|
+
v = find_value 232, :smalldatetime
|
162
|
+
assert_instance_of Time, v
|
163
|
+
assert_equal 2078, v.year
|
164
|
+
assert_equal 06, v.month
|
165
|
+
assert_equal 05, v.day
|
166
|
+
assert_equal 04, v.hour
|
167
|
+
assert_equal 20, v.min
|
168
|
+
assert_equal 00, v.sec
|
169
|
+
assert_equal Time.local(2078,6).utc_offset, find_value(232, :smalldatetime, :timezone => :local).utc_offset
|
170
|
+
assert_equal 0, find_value(232, :smalldatetime, :timezone => :utc).utc_offset
|
233
171
|
end
|
234
172
|
|
235
173
|
it 'casts smallint' do
|
data/test/test_helper.rb
CHANGED
@@ -1,18 +1,11 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
require '
|
3
|
-
require 'bundler'
|
4
|
-
Bundler.setup
|
2
|
+
require 'bundler' ; Bundler.require :development, :test
|
5
3
|
require 'tiny_tds'
|
6
|
-
require 'minitest/spec'
|
7
4
|
require 'minitest/autorun'
|
8
5
|
|
9
6
|
class DateTime
|
10
7
|
def usec
|
11
|
-
|
12
|
-
(sec_fraction * 1_000_000).to_i
|
13
|
-
else
|
14
|
-
(sec_fraction * 60 * 60 * 24 * (10**6)).to_i
|
15
|
-
end
|
8
|
+
(sec_fraction * 1_000_000).to_i
|
16
9
|
end
|
17
10
|
end
|
18
11
|
|
@@ -77,6 +70,7 @@ module TinyTds
|
|
77
70
|
{ :dataserver => ENV['TINYTDS_UNIT_DATASERVER'],
|
78
71
|
:host => ENV['TINYTDS_UNIT_HOST'],
|
79
72
|
:port => ENV['TINYTDS_UNIT_PORT'],
|
73
|
+
:tds_version => ENV['TINYTDS_UNIT_VERSION'],
|
80
74
|
:username => username,
|
81
75
|
:password => password,
|
82
76
|
:database => 'tinytdstest',
|
@@ -118,31 +112,11 @@ module TinyTds
|
|
118
112
|
end
|
119
113
|
|
120
114
|
def assert_binary_encoding(value)
|
121
|
-
assert_equal Encoding.find('BINARY'), value.encoding
|
115
|
+
assert_equal Encoding.find('BINARY'), value.encoding
|
122
116
|
end
|
123
117
|
|
124
118
|
def assert_utf8_encoding(value)
|
125
|
-
assert_equal Encoding.find('UTF-8'), value.encoding
|
126
|
-
end
|
127
|
-
|
128
|
-
def ruby18?
|
129
|
-
RUBY_VERSION < '1.9'
|
130
|
-
end
|
131
|
-
|
132
|
-
def ruby186?
|
133
|
-
RUBY_VERSION == '1.8.6'
|
134
|
-
end
|
135
|
-
|
136
|
-
def ruby19?
|
137
|
-
RUBY_VERSION >= '1.9'
|
138
|
-
end
|
139
|
-
|
140
|
-
def ruby192?
|
141
|
-
RUBY_VERSION == '1.9.2'
|
142
|
-
end
|
143
|
-
|
144
|
-
def ruby32bit?
|
145
|
-
1.size == 4
|
119
|
+
assert_equal Encoding.find('UTF-8'), value.encoding
|
146
120
|
end
|
147
121
|
|
148
122
|
def rubyRbx?
|
@@ -152,8 +126,7 @@ module TinyTds
|
|
152
126
|
def load_current_schema
|
153
127
|
loader = new_connection
|
154
128
|
schema_file = File.expand_path File.join(File.dirname(__FILE__), 'schema', "#{current_schema}.sql")
|
155
|
-
schema_sql =
|
156
|
-
|
129
|
+
schema_sql = File.open(schema_file,"rb:UTF-8") { |f|f.read }
|
157
130
|
loader.execute(drop_sql).each
|
158
131
|
loader.execute(schema_sql).cancel
|
159
132
|
loader.execute(sp_sql).cancel
|
data/test/thread_test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'logger'
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
class ThreadTest < TinyTds::TestCase
|
6
|
+
|
7
|
+
describe 'Threaded SELECT queries' do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@logger = Logger.new $stdout
|
11
|
+
@logger.level = Logger::WARN
|
12
|
+
@poolsize = 4
|
13
|
+
@numthreads = 10
|
14
|
+
@query = "waitfor delay '00:00:01'"
|
15
|
+
@pool = ConnectionPool.new(:size => @poolsize, :timeout => 5) { new_connection }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should finish faster in parallel' do
|
19
|
+
x = Benchmark.realtime do
|
20
|
+
threads = []
|
21
|
+
@numthreads.times do |i|
|
22
|
+
start = Time.new
|
23
|
+
threads << Thread.new do
|
24
|
+
ts = Time.new
|
25
|
+
@pool.with do |client|
|
26
|
+
result = client.execute @query
|
27
|
+
result.each { |r| puts r }
|
28
|
+
end
|
29
|
+
te = Time.new
|
30
|
+
@logger.info "Thread #{i} finished in #{te - ts} thread seconds, #{te - start} real seconds"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
threads.each { |t| t.join }
|
34
|
+
end
|
35
|
+
assert x < @numthreads, "#{x} is not faster than #{@numthreads} seconds"
|
36
|
+
mintime = (1.0*@numthreads/@poolsize).ceil
|
37
|
+
@logger.info "#{@numthreads} queries on #{@poolsize} threads: #{x} sec. Minimum time: #{mintime} sec."
|
38
|
+
assert x > mintime, "#{x} is not slower than #{mintime} seconds"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
metadata
CHANGED
@@ -1,118 +1,126 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 6
|
9
|
-
- 0
|
10
|
-
- rc
|
11
|
-
- 1
|
12
|
-
version: 0.6.0.rc1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.6.0
|
13
6
|
platform: ruby
|
14
|
-
authors:
|
7
|
+
authors:
|
15
8
|
- Ken Collins
|
16
9
|
- Erik Bryn
|
17
10
|
autorequire:
|
18
11
|
bindir: bin
|
19
12
|
cert_chain: []
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
dependencies:
|
24
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
25
16
|
name: rake
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.2
|
26
23
|
prerelease: false
|
27
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
25
|
none: false
|
29
|
-
requirements:
|
26
|
+
requirements:
|
30
27
|
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
hash: 63
|
33
|
-
segments:
|
34
|
-
- 0
|
35
|
-
- 9
|
36
|
-
- 2
|
28
|
+
- !ruby/object:Gem::Version
|
37
29
|
version: 0.9.2
|
38
30
|
type: :development
|
39
|
-
|
40
|
-
- !ruby/object:Gem::Dependency
|
31
|
+
- !ruby/object:Gem::Dependency
|
41
32
|
name: mini_portile
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.5.0
|
42
39
|
prerelease: false
|
43
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
41
|
none: false
|
45
|
-
requirements:
|
42
|
+
requirements:
|
46
43
|
- - ~>
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
hash: 11
|
49
|
-
segments:
|
50
|
-
- 0
|
51
|
-
- 5
|
52
|
-
- 0
|
44
|
+
- !ruby/object:Gem::Version
|
53
45
|
version: 0.5.0
|
54
46
|
type: :development
|
55
|
-
|
56
|
-
- !ruby/object:Gem::Dependency
|
47
|
+
- !ruby/object:Gem::Dependency
|
57
48
|
name: rake-compiler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.8.1
|
58
55
|
prerelease: false
|
59
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
57
|
none: false
|
61
|
-
requirements:
|
62
|
-
- -
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
hash: 61
|
65
|
-
segments:
|
66
|
-
- 0
|
67
|
-
- 8
|
68
|
-
- 1
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
69
61
|
version: 0.8.1
|
70
62
|
type: :development
|
71
|
-
|
72
|
-
- !ruby/object:Gem::Dependency
|
63
|
+
- !ruby/object:Gem::Dependency
|
73
64
|
name: activesupport
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '3.0'
|
74
71
|
prerelease: false
|
75
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
73
|
none: false
|
77
|
-
requirements:
|
74
|
+
requirements:
|
78
75
|
- - ~>
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
segments:
|
82
|
-
- 3
|
83
|
-
- 0
|
84
|
-
version: "3.0"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.0'
|
85
78
|
type: :development
|
86
|
-
|
87
|
-
- !ruby/object:Gem::Dependency
|
79
|
+
- !ruby/object:Gem::Dependency
|
88
80
|
name: minitest
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
89
87
|
prerelease: false
|
90
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
type: :development
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: connection_pool
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
91
98
|
none: false
|
92
|
-
requirements:
|
93
|
-
- -
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
requirements:
|
100
|
+
- - ~>
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.9.2
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.9.2
|
99
110
|
type: :development
|
100
|
-
|
101
|
-
|
102
|
-
email:
|
111
|
+
description: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
112
|
+
Developed for the ActiveRecord SQL Server adapter.
|
113
|
+
email:
|
103
114
|
- ken@metaskills.net
|
104
115
|
executables: []
|
105
|
-
|
106
|
-
extensions:
|
116
|
+
extensions:
|
107
117
|
- ext/tiny_tds/extconf.rb
|
108
118
|
extra_rdoc_files: []
|
109
|
-
|
110
|
-
files:
|
119
|
+
files:
|
111
120
|
- .gitignore
|
112
121
|
- CHANGELOG
|
113
122
|
- Gemfile
|
114
123
|
- MIT-LICENSE
|
115
|
-
- NOTES
|
116
124
|
- README.md
|
117
125
|
- Rakefile
|
118
126
|
- ext/patch/sspi_w_kerberos.diff
|
@@ -142,43 +150,33 @@ files:
|
|
142
150
|
- test/schema/sybase_ase.sql
|
143
151
|
- test/schema_test.rb
|
144
152
|
- test/test_helper.rb
|
145
|
-
|
153
|
+
- test/thread_test.rb
|
146
154
|
homepage: http://github.com/rails-sqlserver/tiny_tds
|
147
155
|
licenses: []
|
148
|
-
|
149
156
|
post_install_message:
|
150
|
-
rdoc_options:
|
157
|
+
rdoc_options:
|
151
158
|
- --charset=UTF-8
|
152
|
-
require_paths:
|
159
|
+
require_paths:
|
153
160
|
- lib
|
154
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
162
|
none: false
|
156
|
-
requirements:
|
157
|
-
- -
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
|
160
|
-
|
161
|
-
- 0
|
162
|
-
version: "0"
|
163
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
168
|
none: false
|
165
|
-
requirements:
|
166
|
-
- -
|
167
|
-
- !ruby/object:Gem::Version
|
168
|
-
|
169
|
-
segments:
|
170
|
-
- 1
|
171
|
-
- 3
|
172
|
-
- 1
|
173
|
-
version: 1.3.1
|
169
|
+
requirements:
|
170
|
+
- - ! '>='
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
174
173
|
requirements: []
|
175
|
-
|
176
174
|
rubyforge_project:
|
177
|
-
rubygems_version: 1.
|
175
|
+
rubygems_version: 1.8.25
|
178
176
|
signing_key:
|
179
177
|
specification_version: 3
|
180
178
|
summary: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
181
|
-
test_files:
|
179
|
+
test_files:
|
182
180
|
- test/benchmark/query.rb
|
183
181
|
- test/benchmark/query_odbc.rb
|
184
182
|
- test/benchmark/query_tinytds.rb
|
@@ -192,3 +190,4 @@ test_files:
|
|
192
190
|
- test/schema/sybase_ase.sql
|
193
191
|
- test/schema_test.rb
|
194
192
|
- test/test_helper.rb
|
193
|
+
- test/thread_test.rb
|
data/NOTES
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
|
2
|
-
TODO
|
3
|
-
|
4
|
-
* Client & Connection
|
5
|
-
- Make a #ping method that does the "SELECT 1" when not closed.
|
6
|
-
- Interrupt handler to cancel a bad SELECT * or long SQL. Maybe use dbsetinterrupt
|
7
|
-
- Integrate rb_thread_blocking_region where we can in your extension for proper threading in 1.9.2
|
8
|
-
|
9
|
-
* Result Set
|
10
|
-
- See if we can make a binary string of [timestamp] type.
|
11
|
-
|