tiny_tds 2.1.3 → 2.1.4.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +0 -0
- data/.gitattributes +0 -0
- data/.gitignore +0 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +0 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/ISSUE_TEMPLATE.md +0 -0
- data/MIT-LICENSE +0 -0
- data/README.md +5 -2
- data/Rakefile +0 -0
- data/VERSION +1 -1
- data/appveyor.yml +13 -1
- data/ext/tiny_tds/client.c +74 -30
- data/ext/tiny_tds/client.h +4 -2
- data/ext/tiny_tds/extconf.rb +0 -0
- data/ext/tiny_tds/extconsts.rb +0 -0
- data/ext/tiny_tds/result.c +18 -9
- data/ext/tiny_tds/result.h +0 -0
- data/ext/tiny_tds/tiny_tds_ext.c +0 -0
- data/ext/tiny_tds/tiny_tds_ext.h +0 -0
- data/lib/tiny_tds.rb +0 -0
- data/lib/tiny_tds/bin.rb +0 -0
- data/lib/tiny_tds/client.rb +0 -0
- data/lib/tiny_tds/error.rb +0 -0
- data/lib/tiny_tds/gem.rb +0 -0
- data/lib/tiny_tds/result.rb +0 -0
- data/lib/tiny_tds/version.rb +0 -0
- data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +0 -0
- data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +0 -0
- data/patches/libiconv/1.14/1-avoid-gets-error.patch +0 -0
- data/tasks/native_gem.rake +0 -0
- data/tasks/package.rake +0 -0
- data/tasks/ports.rake +0 -0
- data/tasks/ports/freetds.rb +0 -0
- data/tasks/ports/libiconv.rb +0 -0
- data/tasks/ports/openssl.rb +0 -0
- data/tasks/ports/recipe.rb +0 -0
- data/tasks/test.rake +0 -0
- data/test/appveyor/dbsetup.ps1 +0 -0
- data/test/appveyor/dbsetup.sql +0 -0
- data/test/benchmark/query.rb +0 -0
- data/test/benchmark/query_odbc.rb +0 -0
- data/test/benchmark/query_tinytds.rb +0 -0
- data/test/client_test.rb +52 -47
- data/test/gem_test.rb +15 -15
- data/test/result_test.rb +59 -42
- data/test/schema/sqlserver_2000.sql +0 -0
- data/test/schema/sqlserver_2005.sql +0 -0
- data/test/schema/sqlserver_2008.sql +0 -0
- data/test/schema/sqlserver_2014.sql +0 -0
- data/test/schema/sqlserver_2016.sql +0 -0
- data/test/schema/sqlserver_azure.sql +0 -0
- data/test/schema/sybase_ase.sql +0 -0
- data/test/schema_test.rb +12 -12
- data/test/test_helper.rb +41 -4
- data/test/thread_test.rb +1 -1
- data/tiny_tds.gemspec +0 -0
- metadata +27 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef24128290a7b007a49222ec2d4307a834930f2aa6606fc9bc2b464b2d7400bb
|
4
|
+
data.tar.gz: e960731768896511f5592e4abd9768df0cf4a63ba089dd7c391bf845c0924788
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44a3b20f0bb91e24d325305fff06046cecc57d16fc6d8f8f7cc530e12689444b1f6b2c6346857cd11d779e0c30c64ebd856a0c9a9b473fdc1ffcc29edf356f30
|
7
|
+
data.tar.gz: 55c8753d62b46cb1f745f2d6b0a9a3f5e270e83f7a956dc03be540e4ed08aa1a7754c4c6462ba9ed58ad15c37c9f8a5be8f1b8236996999dec13d425cf9aadc5
|
data/.codeclimate.yml
CHANGED
File without changes
|
data/.gitattributes
CHANGED
File without changes
|
data/.gitignore
CHANGED
File without changes
|
data/.rubocop.yml
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## (unreleased)
|
2
2
|
|
3
|
+
## 2.1.4
|
4
|
+
|
5
|
+
* todo: changelog for info messages
|
6
|
+
* todo: changelog for network timeouts
|
7
|
+
|
3
8
|
## 2.1.3
|
4
9
|
|
5
10
|
* Removed old/unused appveyor config
|
@@ -215,6 +220,8 @@ Use both dbsetversion() vs. dbsetlversion. Partially reverts #62.
|
|
215
220
|
state of the client and the need to use Result#cancel to stop processing active results. It is also
|
216
221
|
safe to call Result#cancel over and over again.
|
217
222
|
* Look for the syb headers only.
|
223
|
+
* Fix minitest global matchers warnings.
|
224
|
+
* Fix test warnings.
|
218
225
|
|
219
226
|
|
220
227
|
## 0.3.2
|
data/CODE_OF_CONDUCT.md
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/ISSUE_TEMPLATE.md
CHANGED
File without changes
|
data/MIT-LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
* [![TravisCI](https://travis-ci.org/rails-sqlserver/tiny_tds.svg?branch=master)](https://travis-ci.org/rails-sqlserver/tiny_tds) - TravisCI
|
4
4
|
* [![Build Status](https://ci.appveyor.com/api/projects/status/g2bhhbsdkx0mal55/branch/master?svg=true)](https://ci.appveyor.com/project/rails-sqlserver/tiny-tds/branch/master) - Appveyor
|
5
5
|
* [![Gem Version](https://img.shields.io/gem/v/tiny_tds.svg)](https://rubygems.org/gems/tiny_tds) - Gem Version
|
6
|
-
* [![Dependency Status](https://dependencyci.com/github/rails-sqlserver/tiny_tds/badge)](https://dependencyci.com/github/rails-sqlserver/tiny_tds) - Dependency Status
|
7
6
|
* [![Gitter chat](https://img.shields.io/badge/%E2%8A%AA%20GITTER%20-JOIN%20CHAT%20%E2%86%92-brightgreen.svg?style=flat)](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) - Community
|
8
7
|
|
9
8
|
|
@@ -111,7 +110,7 @@ Creating a new client takes a hash of options. For valid iconv encoding options,
|
|
111
110
|
* :appname - Short string seen in SQL Servers process/activity window.
|
112
111
|
* :tds_version - TDS version. Defaults to "7.3".
|
113
112
|
* :login_timeout - Seconds to wait for login. Default to 60 seconds.
|
114
|
-
* :timeout - Seconds to wait for a response to a SQL command. Default 5 seconds. Prior to 1.0rc5, FreeTDS was unable to set the timeout on a per-client basis, permitting only a global timeout value. This means that if you're using an older version, the timeout values for all clients will be overwritten each time you instantiate a new `TinyTds::Client` object. If you are using 1.0rc5 or later, all clients will have an independent timeout setting as you'd expect.
|
113
|
+
* :timeout - Seconds to wait for a response to a SQL command. Default 5 seconds. Prior to 1.0rc5, FreeTDS was unable to set the timeout on a per-client basis, permitting only a global timeout value. This means that if you're using an older version, the timeout values for all clients will be overwritten each time you instantiate a new `TinyTds::Client` object. If you are using 1.0rc5 or later, all clients will have an independent timeout setting as you'd expect. Timeouts caused by network failure will raise a timeout error 1 second after the configured timeout limit is hit (see [#481](https://github.com/rails-sqlserver/tiny_tds/pull/481) for details).
|
115
114
|
* :encoding - Any valid iconv value like CP1251 or ISO-8859-1. Default UTF-8.
|
116
115
|
* :azure - Pass true to signal that you are connecting to azure.
|
117
116
|
* :contained - Pass true to signal that you are connecting with a contained database user.
|
@@ -323,6 +322,10 @@ By default row caching is turned on because the SQL Server adapter for ActiveRec
|
|
323
322
|
TinyTDS takes an opinionated stance on how we handle encoding errors. First, we treat errors differently on reads vs. writes. Our opinion is that if you are reading bad data due to your client's encoding option, you would rather just find `?` marks in your strings vs being blocked with exceptions. This is how things wold work via ODBC or SMS. On the other hand, writes will raise an exception. In this case we raise the SYBEICONVO/2402 error message which has a description of `Error converting characters into server's character set. Some character(s) could not be converted.`. Even though the severity of this message is only a `4` and TinyTDS will automatically strip/ignore unknown characters, we feel you should know that you are inserting bad encodings. In this way, a transaction can be rolled back, etc. Remember, any database write that has bad characters due to the client encoding will still be written to the database, but it is up to you rollback said write if needed. Most ORMs like ActiveRecord handle this scenario just fine.
|
324
323
|
|
325
324
|
|
325
|
+
## Timeout Error Handling
|
326
|
+
|
327
|
+
TinyTDS will raise a `TinyTDS::Error` when a timeout is reached based on the options supplied to the client. Depending on the reason for the timeout, the connection could be dead or alive. When db processing is the cause for the timeout, the connection should still be usable after the error is raised. When network failure is the cause of the timeout, the connection will be dead. If you attempt to execute another command batch on a dead connection you will see a `DBPROCESS is dead or not enabled` error. Therefore, it is recommended to check for a `dead?` connection before trying to execute another command batch.
|
328
|
+
|
326
329
|
## Binstubs
|
327
330
|
|
328
331
|
The TinyTDS gem uses binstub wrappers which mirror compiled [FreeTDS Utilities](http://www.freetds.org/userguide/usefreetds.htm) binaries. These native executables are usually installed at the system level when installing FreeTDS. However, when using MiniPortile to install TinyTDS as we do with Windows binaries, these binstubs will find and prefer local gem `exe` directory executables. These are the following binstubs we wrap.
|
data/Rakefile
CHANGED
File without changes
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.4.pre
|
data/appveyor.yml
CHANGED
@@ -19,7 +19,19 @@ install:
|
|
19
19
|
- perl --version
|
20
20
|
- ruby --version
|
21
21
|
- gem --version
|
22
|
-
|
22
|
+
# Update keyring according to https://www.msys2.org/news/#2020-06-29-new-packagers
|
23
|
+
- C:\msys64\usr\bin\curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz
|
24
|
+
- C:\msys64\usr\bin\curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig
|
25
|
+
- ridk exec bash -c "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
26
|
+
- ridk exec bash -c "pacman -U --noconfirm --config <(echo) msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
27
|
+
# Update zstd and pacman first https://github.com/msys2/MSYS2-packages/issues/2300
|
28
|
+
- C:\msys64\usr\bin\pacman --noconfirm --upgrade https://repo.msys2.org/msys/x86_64/zstd-1.4.7-1-x86_64.pkg.tar.xz # Must come First, or else pacman will install 1.4.8
|
29
|
+
- C:\msys64\usr\bin\pacman --noconfirm --upgrade https://repo.msys2.org/msys/x86_64/pacman-5.2.2-5-x86_64.pkg.tar.xz
|
30
|
+
# update packages
|
31
|
+
- C:\msys64\usr\bin\pacman --noconfirm --ask 20 --sync --refresh --refresh --sysupgrade --sysupgrade
|
32
|
+
# Kill all running msys2 binaries to avoid error "size of shared memory region changed".
|
33
|
+
# See https://github.com/msys2/MSYS2-packages/issues/258
|
34
|
+
- powershell -Command "Get-Process | Where-Object {$_.path -like 'C:\msys64*'} | Stop-Process"
|
23
35
|
# prevent freetds to link to wrong ws2_32 lib on i686-w64-mingw32
|
24
36
|
- c:/msys64/usr/bin/rm /usr/lib/w32api/libws2_32.a
|
25
37
|
# Set up project prerequisits
|
data/ext/tiny_tds/client.c
CHANGED
@@ -57,6 +57,16 @@ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int is_message, int cancel, cons
|
|
57
57
|
|
58
58
|
|
59
59
|
// Lib Backend (Memory Management & Handlers)
|
60
|
+
static void push_userdata_error(tinytds_client_userdata *userdata, tinytds_errordata error) {
|
61
|
+
// reallocate memory for the array as needed
|
62
|
+
if (userdata->nonblocking_errors_size == userdata->nonblocking_errors_length) {
|
63
|
+
userdata->nonblocking_errors_size *= 2;
|
64
|
+
userdata->nonblocking_errors = realloc(userdata->nonblocking_errors, userdata->nonblocking_errors_size * sizeof(tinytds_errordata));
|
65
|
+
}
|
66
|
+
|
67
|
+
userdata->nonblocking_errors[userdata->nonblocking_errors_length] = error;
|
68
|
+
userdata->nonblocking_errors_length++;
|
69
|
+
}
|
60
70
|
|
61
71
|
int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) {
|
62
72
|
static const char *source = "error";
|
@@ -86,7 +96,13 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
86
96
|
but we don't ever want to automatically retry. Instead have the app
|
87
97
|
decide what to do.
|
88
98
|
*/
|
89
|
-
|
99
|
+
if (userdata->timing_out) {
|
100
|
+
return INT_CANCEL;
|
101
|
+
}
|
102
|
+
else {
|
103
|
+
userdata->timing_out = 1;
|
104
|
+
return_value = INT_TIMEOUT;
|
105
|
+
}
|
90
106
|
cancel = 1;
|
91
107
|
break;
|
92
108
|
|
@@ -111,24 +127,16 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
111
127
|
userdata->dbcancel_sent = 1;
|
112
128
|
}
|
113
129
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
strncpy(userdata->nonblocking_error.error, dberrstr, ERROR_MSG_SIZE);
|
125
|
-
strncpy(userdata->nonblocking_error.source, source, ERROR_MSG_SIZE);
|
126
|
-
userdata->nonblocking_error.severity = severity;
|
127
|
-
userdata->nonblocking_error.dberr = dberr;
|
128
|
-
userdata->nonblocking_error.oserr = oserr;
|
129
|
-
userdata->nonblocking_error.is_set = 1;
|
130
|
-
}
|
131
|
-
|
130
|
+
tinytds_errordata error = {
|
131
|
+
.is_message = 0,
|
132
|
+
.cancel = cancel,
|
133
|
+
.severity = severity,
|
134
|
+
.dberr = dberr,
|
135
|
+
.oserr = oserr
|
136
|
+
};
|
137
|
+
strncpy(error.error, dberrstr, ERROR_MSG_SIZE);
|
138
|
+
strncpy(error.source, source, ERROR_MSG_SIZE);
|
139
|
+
push_userdata_error(userdata, error);
|
132
140
|
} else {
|
133
141
|
rb_tinytds_raise_error(dbproc, 0, cancel, dberrstr, source, severity, dberr, oserr);
|
134
142
|
}
|
@@ -144,16 +152,21 @@ int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severi
|
|
144
152
|
|
145
153
|
// See tinytds_err_handler() for info about why we do this
|
146
154
|
if (userdata && userdata->nonblocking) {
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
/*
|
156
|
+
In the case of non-blocking command batch execution we can receive multiple messages
|
157
|
+
(including errors). We keep track of those here so they can be processed once the
|
158
|
+
non-blocking call returns.
|
159
|
+
*/
|
160
|
+
tinytds_errordata error = {
|
161
|
+
.is_message = !is_message_an_error,
|
162
|
+
.cancel = is_message_an_error,
|
163
|
+
.severity = severity,
|
164
|
+
.dberr = msgno,
|
165
|
+
.oserr = msgstate
|
166
|
+
};
|
167
|
+
strncpy(error.error, msgtext, ERROR_MSG_SIZE);
|
168
|
+
strncpy(error.source, source, ERROR_MSG_SIZE);
|
169
|
+
push_userdata_error(userdata, error);
|
157
170
|
|
158
171
|
if (is_message_an_error && !dbdead(dbproc) && !userdata->closed) {
|
159
172
|
dbcancel(dbproc);
|
@@ -165,13 +178,43 @@ int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severi
|
|
165
178
|
return 0;
|
166
179
|
}
|
167
180
|
|
181
|
+
/*
|
182
|
+
Used by dbsetinterrupt -
|
183
|
+
This gets called periodically while waiting on a read from the server
|
184
|
+
Right now, we only care about cases where a read from the server is
|
185
|
+
taking longer than the specified timeout and dbcancel is not working.
|
186
|
+
In these cases we decide that we actually want to handle the interrupt
|
187
|
+
*/
|
188
|
+
static int check_interrupt(void *ptr) {
|
189
|
+
GET_CLIENT_USERDATA((DBPROCESS *)ptr);
|
190
|
+
return userdata->timing_out;
|
191
|
+
}
|
192
|
+
|
193
|
+
/*
|
194
|
+
Used by dbsetinterrupt -
|
195
|
+
This gets called if check_interrupt returns TRUE.
|
196
|
+
Right now, this is only used in cases where a read from the server is
|
197
|
+
taking longer than the specified timeout and dbcancel is not working.
|
198
|
+
Return INT_CANCEL to abort the current command batch.
|
199
|
+
*/
|
200
|
+
static int handle_interrupt(void *ptr) {
|
201
|
+
GET_CLIENT_USERDATA((DBPROCESS *)ptr);
|
202
|
+
if (userdata->timing_out) {
|
203
|
+
return INT_CANCEL;
|
204
|
+
}
|
205
|
+
return INT_CONTINUE;
|
206
|
+
}
|
207
|
+
|
168
208
|
static void rb_tinytds_client_reset_userdata(tinytds_client_userdata *userdata) {
|
169
209
|
userdata->timing_out = 0;
|
170
210
|
userdata->dbsql_sent = 0;
|
171
211
|
userdata->dbsqlok_sent = 0;
|
172
212
|
userdata->dbcancel_sent = 0;
|
173
213
|
userdata->nonblocking = 0;
|
174
|
-
|
214
|
+
// the following is mainly done for consistency since the values are reset accordingly in nogvl_setup/cleanup.
|
215
|
+
// the nonblocking_errors array does not need to be freed here. That is done as part of nogvl_cleanup.
|
216
|
+
userdata->nonblocking_errors_length = 0;
|
217
|
+
userdata->nonblocking_errors_size = 0;
|
175
218
|
}
|
176
219
|
|
177
220
|
static void rb_tinytds_client_mark(void *ptr) {
|
@@ -381,6 +424,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
381
424
|
}
|
382
425
|
}
|
383
426
|
dbsetuserdata(cwrap->client, (BYTE*)cwrap->userdata);
|
427
|
+
dbsetinterrupt(cwrap->client, check_interrupt, handle_interrupt);
|
384
428
|
cwrap->userdata->closed = 0;
|
385
429
|
if (!NIL_P(database) && (azure != Qtrue)) {
|
386
430
|
dbuse(cwrap->client, StringValueCStr(database));
|
data/ext/tiny_tds/client.h
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
void init_tinytds_client();
|
6
6
|
|
7
7
|
#define ERROR_MSG_SIZE 1024
|
8
|
+
#define ERRORS_STACK_INIT_SIZE 2
|
8
9
|
|
9
10
|
typedef struct {
|
10
|
-
short int is_set;
|
11
11
|
int is_message;
|
12
12
|
int cancel;
|
13
13
|
char error[ERROR_MSG_SIZE];
|
@@ -25,7 +25,9 @@ typedef struct {
|
|
25
25
|
RETCODE dbsqlok_retcode;
|
26
26
|
short int dbcancel_sent;
|
27
27
|
short int nonblocking;
|
28
|
-
|
28
|
+
short int nonblocking_errors_length;
|
29
|
+
short int nonblocking_errors_size;
|
30
|
+
tinytds_errordata *nonblocking_errors;
|
29
31
|
VALUE message_handler;
|
30
32
|
} tinytds_client_userdata;
|
31
33
|
|
data/ext/tiny_tds/extconf.rb
CHANGED
File without changes
|
data/ext/tiny_tds/extconsts.rb
CHANGED
File without changes
|
data/ext/tiny_tds/result.c
CHANGED
@@ -86,26 +86,35 @@ static void dbcancel_ubf(DBPROCESS *client) {
|
|
86
86
|
static void nogvl_setup(DBPROCESS *client) {
|
87
87
|
GET_CLIENT_USERDATA(client);
|
88
88
|
userdata->nonblocking = 1;
|
89
|
+
userdata->nonblocking_errors_length = 0;
|
90
|
+
userdata->nonblocking_errors = malloc(ERRORS_STACK_INIT_SIZE * sizeof(tinytds_errordata));
|
91
|
+
userdata->nonblocking_errors_size = ERRORS_STACK_INIT_SIZE;
|
89
92
|
}
|
90
93
|
|
91
94
|
static void nogvl_cleanup(DBPROCESS *client) {
|
92
95
|
GET_CLIENT_USERDATA(client);
|
93
96
|
userdata->nonblocking = 0;
|
97
|
+
userdata->timing_out = 0;
|
94
98
|
/*
|
95
99
|
Now that the blocking operation is done, we can finally throw any
|
96
100
|
exceptions based on errors from SQL Server.
|
97
101
|
*/
|
98
|
-
|
99
|
-
|
102
|
+
for (short int i = 0; i < userdata->nonblocking_errors_length; i++) {
|
103
|
+
tinytds_errordata error = userdata->nonblocking_errors[i];
|
100
104
|
rb_tinytds_raise_error(client,
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
105
|
+
error.is_message,
|
106
|
+
error.cancel,
|
107
|
+
error.error,
|
108
|
+
error.source,
|
109
|
+
error.severity,
|
110
|
+
error.dberr,
|
111
|
+
error.oserr
|
112
|
+
);
|
108
113
|
}
|
114
|
+
|
115
|
+
free(userdata->nonblocking_errors);
|
116
|
+
userdata->nonblocking_errors_length = 0;
|
117
|
+
userdata->nonblocking_errors_size = 0;
|
109
118
|
}
|
110
119
|
|
111
120
|
static RETCODE nogvl_dbsqlok(DBPROCESS *client) {
|
data/ext/tiny_tds/result.h
CHANGED
File without changes
|
data/ext/tiny_tds/tiny_tds_ext.c
CHANGED
File without changes
|
data/ext/tiny_tds/tiny_tds_ext.h
CHANGED
File without changes
|
data/lib/tiny_tds.rb
CHANGED
File without changes
|
data/lib/tiny_tds/bin.rb
CHANGED
File without changes
|
data/lib/tiny_tds/client.rb
CHANGED
File without changes
|
data/lib/tiny_tds/error.rb
CHANGED
File without changes
|
data/lib/tiny_tds/gem.rb
CHANGED
File without changes
|
data/lib/tiny_tds/result.rb
CHANGED
File without changes
|
data/lib/tiny_tds/version.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/tasks/native_gem.rake
CHANGED
File without changes
|
data/tasks/package.rake
CHANGED
File without changes
|
data/tasks/ports.rake
CHANGED
File without changes
|
data/tasks/ports/freetds.rb
CHANGED
File without changes
|
data/tasks/ports/libiconv.rb
CHANGED
File without changes
|
data/tasks/ports/openssl.rb
CHANGED
File without changes
|
data/tasks/ports/recipe.rb
CHANGED
File without changes
|
data/tasks/test.rake
CHANGED
File without changes
|
data/test/appveyor/dbsetup.ps1
CHANGED
File without changes
|
data/test/appveyor/dbsetup.sql
CHANGED
File without changes
|
data/test/benchmark/query.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/test/client_test.rb
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
require 'test_helper'
|
3
3
|
|
4
4
|
class ClientTest < TinyTds::TestCase
|
5
|
-
|
6
|
-
describe 'With valid credentials' do
|
7
|
-
|
5
|
+
describe 'with valid credentials' do
|
8
6
|
before do
|
9
7
|
@client = new_connection
|
10
8
|
end
|
@@ -67,7 +65,6 @@ class ClientTest < TinyTds::TestCase
|
|
67
65
|
client.close if client
|
68
66
|
end
|
69
67
|
end unless sqlserver_azure?
|
70
|
-
|
71
68
|
end
|
72
69
|
|
73
70
|
describe 'With in-valid options' do
|
@@ -132,14 +129,12 @@ class ClientTest < TinyTds::TestCase
|
|
132
129
|
end
|
133
130
|
end
|
134
131
|
|
135
|
-
it '
|
136
|
-
skip
|
132
|
+
it 'raises TinyTds exception with sql batch timeout due to network failure' do
|
133
|
+
skip if ENV['CI'] && ENV['APPVEYOR_BUILD_FOLDER'] # only CI using docker
|
137
134
|
begin
|
138
|
-
client = new_connection :
|
135
|
+
client = new_connection timeout: 2
|
139
136
|
assert_client_works(client)
|
140
|
-
|
141
|
-
sleep 10
|
142
|
-
STDOUT.puts "This should not get stuck past 6 seconds!"
|
137
|
+
docker_container('pause', wait_for: 1)
|
143
138
|
action = lambda { client.execute('SELECT 1 as [one]').each }
|
144
139
|
assert_raise_tinytds_error(action) do |e|
|
145
140
|
assert_equal 20003, e.db_error_number
|
@@ -147,12 +142,11 @@ class ClientTest < TinyTds::TestCase
|
|
147
142
|
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
148
143
|
end
|
149
144
|
ensure
|
150
|
-
|
151
|
-
sleep 10
|
145
|
+
docker_container('unpause', wait_for: 1)
|
152
146
|
action = lambda { client.execute('SELECT 1 as [one]').each }
|
153
147
|
assert_raise_tinytds_error(action) do |e|
|
154
148
|
assert_equal 20047, e.db_error_number
|
155
|
-
|
149
|
+
assert_includes [1,9], e.severity
|
156
150
|
assert_match %r{dead or not enabled}i, e.message, 'ignore if non-english test run'
|
157
151
|
end
|
158
152
|
close_client(client)
|
@@ -174,57 +168,68 @@ class ClientTest < TinyTds::TestCase
|
|
174
168
|
|
175
169
|
end
|
176
170
|
|
177
|
-
describe '
|
178
|
-
|
171
|
+
describe '#parse_username' do
|
179
172
|
let(:client) { @client = new_connection }
|
180
173
|
|
181
|
-
it '
|
182
|
-
|
183
|
-
|
174
|
+
it 'returns username if azure is not true' do
|
175
|
+
_(
|
176
|
+
client.send(:parse_username, username: 'user@abc123.database.windows.net')
|
177
|
+
).must_equal 'user@abc123.database.windows.net'
|
184
178
|
end
|
185
179
|
|
186
|
-
it '
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
180
|
+
it 'returns short username if azure is true' do
|
181
|
+
_(
|
182
|
+
client.send(
|
183
|
+
:parse_username,
|
184
|
+
username: 'user@abc123.database.windows.net',
|
185
|
+
host: 'abc123.database.windows.net',
|
186
|
+
azure: true
|
187
|
+
)
|
191
188
|
).must_equal 'user@abc123'
|
192
189
|
end
|
193
190
|
|
194
|
-
it '
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
191
|
+
it 'returns full username if azure is false' do
|
192
|
+
_(
|
193
|
+
client.send(
|
194
|
+
:parse_username,
|
195
|
+
username: 'user@abc123.database.windows.net',
|
196
|
+
host: 'abc123.database.windows.net',
|
197
|
+
azure: false
|
198
|
+
)
|
199
199
|
).must_equal 'user@abc123.database.windows.net'
|
200
200
|
end
|
201
201
|
|
202
|
-
it '
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
202
|
+
it 'returns short username if passed and azure is true' do
|
203
|
+
_(
|
204
|
+
client.send(
|
205
|
+
:parse_username,
|
206
|
+
username: 'user@abc123',
|
207
|
+
host: 'abc123.database.windows.net',
|
208
|
+
azure: true
|
209
|
+
)
|
207
210
|
).must_equal 'user@abc123'
|
208
211
|
end
|
209
212
|
|
210
|
-
it '
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
213
|
+
it 'returns username with servername if passed and azure is true' do
|
214
|
+
_(
|
215
|
+
client.send(
|
216
|
+
:parse_username,
|
217
|
+
username: 'user',
|
218
|
+
host: 'abc123.database.windows.net',
|
219
|
+
azure: true
|
220
|
+
)
|
215
221
|
).must_equal 'user@abc123'
|
216
222
|
end
|
217
223
|
|
218
|
-
it '
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
224
|
+
it 'returns username with servername if passed and azure is false' do
|
225
|
+
_(
|
226
|
+
client.send(
|
227
|
+
:parse_username,
|
228
|
+
username: 'user',
|
229
|
+
host: 'abc123.database.windows.net',
|
230
|
+
azure: false
|
231
|
+
)
|
223
232
|
).must_equal 'user'
|
224
233
|
end
|
225
|
-
|
226
234
|
end
|
227
|
-
|
228
|
-
|
229
235
|
end
|
230
|
-
|
data/test/gem_test.rb
CHANGED
@@ -21,13 +21,13 @@ class GemTest < MiniTest::Spec
|
|
21
21
|
let(:root_path) { TinyTds::Gem.root_path }
|
22
22
|
|
23
23
|
it 'should be the root path' do
|
24
|
-
root_path.must_equal gem_root
|
24
|
+
_(root_path).must_equal gem_root
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'should be the root path no matter the cwd' do
|
28
28
|
Dir.chdir '/'
|
29
29
|
|
30
|
-
root_path.must_equal gem_root
|
30
|
+
_(root_path).must_equal gem_root
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -35,19 +35,19 @@ class GemTest < MiniTest::Spec
|
|
35
35
|
let(:ports_root_path) { TinyTds::Gem.ports_root_path }
|
36
36
|
|
37
37
|
it 'should be the ports path' do
|
38
|
-
ports_root_path.must_equal File.join(gem_root,'ports')
|
38
|
+
_(ports_root_path).must_equal File.join(gem_root,'ports')
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should be the ports path no matter the cwd' do
|
42
42
|
Dir.chdir '/'
|
43
43
|
|
44
|
-
ports_root_path.must_equal File.join(gem_root,'ports')
|
44
|
+
_(ports_root_path).must_equal File.join(gem_root,'ports')
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe '#ports_bin_paths' do
|
49
49
|
let(:ports_bin_paths) { TinyTds::Gem.ports_bin_paths }
|
50
|
-
|
50
|
+
|
51
51
|
describe 'when the ports directories exist' do
|
52
52
|
let(:fake_bin_paths) do
|
53
53
|
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
@@ -74,12 +74,12 @@ class GemTest < MiniTest::Spec
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'should return all the bin directories' do
|
77
|
-
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
77
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'should return all the bin directories regardless of cwd' do
|
81
81
|
Dir.chdir '/'
|
82
|
-
ports_bin_paths.sort.must_equal fake_bin_paths.sort
|
82
|
+
_(ports_bin_paths.sort).must_equal fake_bin_paths.sort
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -89,19 +89,19 @@ class GemTest < MiniTest::Spec
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'should return no directories' do
|
92
|
-
ports_bin_paths.must_be_empty
|
92
|
+
_(ports_bin_paths).must_be_empty
|
93
93
|
end
|
94
94
|
|
95
95
|
it 'should return no directories regardless of cwd' do
|
96
96
|
Dir.chdir '/'
|
97
|
-
ports_bin_paths.must_be_empty
|
97
|
+
_(ports_bin_paths).must_be_empty
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
describe '#ports_lib_paths' do
|
103
103
|
let(:ports_lib_paths) { TinyTds::Gem.ports_lib_paths }
|
104
|
-
|
104
|
+
|
105
105
|
describe 'when the ports directories exist' do
|
106
106
|
let(:fake_lib_paths) do
|
107
107
|
ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs')
|
@@ -128,12 +128,12 @@ class GemTest < MiniTest::Spec
|
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'should return all the lib directories' do
|
131
|
-
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
131
|
+
_(ports_lib_paths.sort).must_equal fake_lib_paths.sort
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'should return all the lib directories regardless of cwd' do
|
135
135
|
Dir.chdir '/'
|
136
|
-
ports_lib_paths.sort.must_equal fake_lib_paths.sort
|
136
|
+
_(ports_lib_paths.sort).must_equal fake_lib_paths.sort
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -144,12 +144,12 @@ class GemTest < MiniTest::Spec
|
|
144
144
|
|
145
145
|
|
146
146
|
it 'should return no directories' do
|
147
|
-
ports_lib_paths.must_be_empty
|
147
|
+
_(ports_lib_paths).must_be_empty
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'should return no directories regardless of cwd' do
|
151
151
|
Dir.chdir '/'
|
152
|
-
ports_lib_paths.must_be_empty
|
152
|
+
_(ports_lib_paths).must_be_empty
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
@@ -169,7 +169,7 @@ class GemTest < MiniTest::Spec
|
|
169
169
|
end
|
170
170
|
|
171
171
|
it "should return a #{expected} ports host" do
|
172
|
-
TinyTds::Gem.ports_host.must_equal expected
|
172
|
+
_(TinyTds::Gem.ports_host).must_equal expected
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
data/test/result_test.rb
CHANGED
@@ -80,7 +80,7 @@ class ResultTest < TinyTds::TestCase
|
|
80
80
|
@client.execute("DELETE FROM [datatypes]").do
|
81
81
|
@client.execute("INSERT INTO [datatypes] ([char_10], [varchar_50]) VALUES ('1', '2')").do
|
82
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"
|
83
|
+
_(result).must_equal "1 test2"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -135,10 +135,10 @@ class ResultTest < TinyTds::TestCase
|
|
135
135
|
text = 'test affected rows sql'
|
136
136
|
@client.execute("DELETE FROM [datatypes]").do
|
137
137
|
afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
|
138
|
-
['Fixnum', 'Integer'].must_include afrows.class.name
|
138
|
+
_(['Fixnum', 'Integer']).must_include afrows.class.name
|
139
139
|
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
140
140
|
pk1 = @client.execute(@client.identity_sql).each.first['Ident']
|
141
|
-
['Fixnum', 'Integer'].must_include pk1.class.name, 'we it be able to CAST to bigint'
|
141
|
+
_(['Fixnum', 'Integer']).must_include pk1.class.name, 'we it be able to CAST to bigint'
|
142
142
|
@client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
143
143
|
afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
|
144
144
|
assert_equal 1, afrows
|
@@ -215,34 +215,34 @@ class ResultTest < TinyTds::TestCase
|
|
215
215
|
@client.execute("DELETE FROM [datatypes]").do
|
216
216
|
@client.execute("ROLLBACK TRANSACTION").do
|
217
217
|
count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
|
218
|
-
|
218
|
+
_(count).wont_equal 0
|
219
219
|
end
|
220
220
|
|
221
221
|
it 'has a #fields accessor with logic default and valid outcome' do
|
222
222
|
result = @client.execute(@query1)
|
223
|
-
result.fields.must_equal ['one']
|
223
|
+
_(result.fields).must_equal ['one']
|
224
224
|
result.each
|
225
|
-
result.fields.must_equal ['one']
|
225
|
+
_(result.fields).must_equal ['one']
|
226
226
|
end
|
227
227
|
|
228
228
|
it 'always returns an array for fields for all sql' do
|
229
229
|
result = @client.execute("USE [tinytdstest]")
|
230
|
-
result.fields.must_equal []
|
230
|
+
_(result.fields).must_equal []
|
231
231
|
result.do
|
232
|
-
result.fields.must_equal []
|
232
|
+
_(result.fields).must_equal []
|
233
233
|
end
|
234
234
|
|
235
235
|
it 'returns fields even when no results are found' do
|
236
236
|
no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'"
|
237
237
|
# Fields before each.
|
238
238
|
result = @client.execute(no_results_query)
|
239
|
-
result.fields.must_equal ['id','varchar_50']
|
239
|
+
_(result.fields).must_equal ['id','varchar_50']
|
240
240
|
result.each
|
241
|
-
result.fields.must_equal ['id','varchar_50']
|
241
|
+
_(result.fields).must_equal ['id','varchar_50']
|
242
242
|
# Each then fields
|
243
243
|
result = @client.execute(no_results_query)
|
244
244
|
result.each
|
245
|
-
result.fields.must_equal ['id','varchar_50']
|
245
|
+
_(result.fields).must_equal ['id','varchar_50']
|
246
246
|
end
|
247
247
|
|
248
248
|
it 'allows the result to be canceled before reading' do
|
@@ -254,27 +254,27 @@ class ResultTest < TinyTds::TestCase
|
|
254
254
|
it 'works in tandem with the client when needing to find out if client has sql sent and result is canceled or not' do
|
255
255
|
# Default state.
|
256
256
|
@client = TinyTds::Client.new(connection_options)
|
257
|
-
@client.sqlsent
|
258
|
-
@client.canceled
|
257
|
+
_(@client.sqlsent?).must_equal false
|
258
|
+
_(@client.canceled?).must_equal false
|
259
259
|
# With active result before and after cancel.
|
260
260
|
result = @client.execute(@query1)
|
261
|
-
@client.sqlsent
|
262
|
-
@client.canceled
|
261
|
+
_(@client.sqlsent?).must_equal true
|
262
|
+
_(@client.canceled?).must_equal false
|
263
263
|
result.cancel
|
264
|
-
@client.sqlsent
|
265
|
-
@client.canceled
|
264
|
+
_(@client.sqlsent?).must_equal false
|
265
|
+
_(@client.canceled?).must_equal true
|
266
266
|
assert result.cancel, 'must be safe to call again'
|
267
267
|
# With each and no block.
|
268
268
|
@client.execute(@query1).each
|
269
|
-
@client.sqlsent
|
270
|
-
@client.canceled
|
269
|
+
_(@client.sqlsent?).must_equal false
|
270
|
+
_(@client.canceled?).must_equal false
|
271
271
|
# With each and block.
|
272
272
|
@client.execute(@query1).each do |row|
|
273
|
-
@client.sqlsent
|
274
|
-
@client.canceled
|
273
|
+
_(@client.sqlsent?).must_equal true, 'when iterating over each row in a block'
|
274
|
+
_(@client.canceled?).must_equal false
|
275
275
|
end
|
276
|
-
@client.sqlsent
|
277
|
-
@client.canceled
|
276
|
+
_(@client.sqlsent?).must_equal false
|
277
|
+
_(@client.canceled?).must_equal false
|
278
278
|
# With each and block canceled half way thru.
|
279
279
|
count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]['count']
|
280
280
|
assert count > 10, 'since we want to cancel early for test'
|
@@ -284,25 +284,25 @@ class ResultTest < TinyTds::TestCase
|
|
284
284
|
break if index > 10
|
285
285
|
index += 1
|
286
286
|
end
|
287
|
-
@client.sqlsent
|
288
|
-
@client.canceled
|
287
|
+
_(@client.sqlsent?).must_equal true
|
288
|
+
_(@client.canceled?).must_equal false
|
289
289
|
result.cancel
|
290
|
-
@client.sqlsent
|
291
|
-
@client.canceled
|
290
|
+
_(@client.sqlsent?).must_equal false
|
291
|
+
_(@client.canceled?).must_equal true
|
292
292
|
# With do method.
|
293
293
|
@client.execute(@query1).do
|
294
|
-
@client.sqlsent
|
295
|
-
@client.canceled
|
294
|
+
_(@client.sqlsent?).must_equal false
|
295
|
+
_(@client.canceled?).must_equal true
|
296
296
|
# With insert method.
|
297
297
|
rollback_transaction(@client) do
|
298
298
|
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('test')").insert
|
299
|
-
@client.sqlsent
|
300
|
-
@client.canceled
|
299
|
+
_(@client.sqlsent?).must_equal false
|
300
|
+
_(@client.canceled?).must_equal true
|
301
301
|
end
|
302
302
|
# With first
|
303
303
|
@client.execute("SELECT [id] FROM [datatypes]").each(:first => true)
|
304
|
-
@client.sqlsent
|
305
|
-
@client.canceled
|
304
|
+
_(@client.sqlsent?).must_equal false
|
305
|
+
_(@client.canceled?).must_equal true
|
306
306
|
end
|
307
307
|
|
308
308
|
it 'use same string object for hash keys' do
|
@@ -337,7 +337,7 @@ class ResultTest < TinyTds::TestCase
|
|
337
337
|
|
338
338
|
it 'with LOGINPROPERTY function' do
|
339
339
|
v = @client.execute("SELECT LOGINPROPERTY('sa', 'IsLocked') as v").first['v']
|
340
|
-
v.must_equal 0
|
340
|
+
_(v).must_equal 0
|
341
341
|
end
|
342
342
|
|
343
343
|
describe 'with multiple result sets' do
|
@@ -652,6 +652,24 @@ class ResultTest < TinyTds::TestCase
|
|
652
652
|
assert_equal 1, messages.length, 'there should be one message after one print statement'
|
653
653
|
assert_equal msg, m.message, 'message text'
|
654
654
|
end
|
655
|
+
|
656
|
+
it 'must raise an error preceded by a `print` message' do
|
657
|
+
messages.clear
|
658
|
+
action = lambda { @client.execute("EXEC tinytds_TestPrintWithError").do }
|
659
|
+
assert_raise_tinytds_error(action) do |e|
|
660
|
+
assert_equal 'hello', messages.first.message, 'message text'
|
661
|
+
|
662
|
+
assert_equal "Error following print", e.message
|
663
|
+
assert_equal 16, e.severity
|
664
|
+
assert_equal 50000, e.db_error_number
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
it 'calls the provided message handler for each of a series of `print` messages' do
|
669
|
+
messages.clear
|
670
|
+
@client.execute("EXEC tinytds_TestSeveralPrints").do
|
671
|
+
assert_equal ['hello 1', 'hello 2', 'hello 3'], messages.map { |e| e.message }, 'message list'
|
672
|
+
end
|
655
673
|
end
|
656
674
|
|
657
675
|
it 'must not raise an error when severity is 10 or less' do
|
@@ -684,7 +702,7 @@ class ResultTest < TinyTds::TestCase
|
|
684
702
|
end
|
685
703
|
|
686
704
|
it 'throws an error when you execute another query with other results pending' do
|
687
|
-
|
705
|
+
@client.execute(@query1)
|
688
706
|
action = lambda { @client.execute(@query1) }
|
689
707
|
assert_raise_tinytds_error(action) do |e|
|
690
708
|
assert_match %r|with results pending|i, e.message
|
@@ -717,22 +735,22 @@ class ResultTest < TinyTds::TestCase
|
|
717
735
|
it 'must not error at all from reading non-convertable charcters and just use ? marks' do
|
718
736
|
close_client
|
719
737
|
@client = new_connection :encoding => 'ASCII'
|
720
|
-
@client.charset.must_equal 'ASCII'
|
721
|
-
find_value(202, :nvarchar_50).must_equal 'test nvarchar_50 ??'
|
738
|
+
_(@client.charset).must_equal 'ASCII'
|
739
|
+
_(find_value(202, :nvarchar_50)).must_equal 'test nvarchar_50 ??'
|
722
740
|
end
|
723
741
|
|
724
742
|
it 'must error gracefully from writing non-convertable characters' do
|
725
743
|
close_client
|
726
744
|
@client = new_connection :encoding => 'ASCII'
|
727
|
-
@client.charset.must_equal 'ASCII'
|
745
|
+
_(@client.charset).must_equal 'ASCII'
|
728
746
|
rollback_transaction(@client) do
|
729
747
|
text = 'Test ✓'
|
730
748
|
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
731
749
|
action = lambda { @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES ('#{text}')").do }
|
732
750
|
assert_raise_tinytds_error(action) do |e|
|
733
|
-
e.message.must_match %r{Unclosed quotation mark}i
|
734
|
-
e.severity.must_equal 15
|
735
|
-
e.db_error_number.must_equal 105
|
751
|
+
_(e.message).must_match %r{Unclosed quotation mark}i
|
752
|
+
_(e.severity).must_equal 15
|
753
|
+
_(e.db_error_number).must_equal 105
|
736
754
|
end
|
737
755
|
assert_followup_query
|
738
756
|
end
|
@@ -770,4 +788,3 @@ class ResultTest < TinyTds::TestCase
|
|
770
788
|
end
|
771
789
|
|
772
790
|
end
|
773
|
-
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/test/schema/sybase_ase.sql
CHANGED
File without changes
|
data/test/schema_test.rb
CHANGED
@@ -14,7 +14,7 @@ class SchemaTest < TinyTds::TestCase
|
|
14
14
|
describe 'for shared types' do
|
15
15
|
|
16
16
|
it 'casts bigint' do
|
17
|
-
assert_equal -9223372036854775807, find_value(11, :bigint)
|
17
|
+
assert_equal (-9223372036854775807), find_value(11, :bigint)
|
18
18
|
assert_equal 9223372036854775806, find_value(12, :bigint)
|
19
19
|
end
|
20
20
|
|
@@ -96,7 +96,7 @@ class SchemaTest < TinyTds::TestCase
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'casts int' do
|
99
|
-
assert_equal -2147483647, find_value(151, :int)
|
99
|
+
assert_equal (-2147483647), find_value(151, :int)
|
100
100
|
assert_equal 2147483646, find_value(152, :int)
|
101
101
|
end
|
102
102
|
|
@@ -170,7 +170,7 @@ class SchemaTest < TinyTds::TestCase
|
|
170
170
|
end
|
171
171
|
|
172
172
|
it 'casts smallint' do
|
173
|
-
assert_equal -32767, find_value(241, :smallint)
|
173
|
+
assert_equal (-32767), find_value(241, :smallint)
|
174
174
|
assert_equal 32766, find_value(242, :smallint)
|
175
175
|
end
|
176
176
|
|
@@ -396,15 +396,15 @@ class SchemaTest < TinyTds::TestCase
|
|
396
396
|
if @client.tds_73?
|
397
397
|
assertions = lambda {
|
398
398
|
assert_instance_of Time, v
|
399
|
-
assert_equal 1984, v.year,
|
400
|
-
assert_equal 1, v.month,
|
401
|
-
assert_equal 24, v.day,
|
402
|
-
assert_equal 4, v.hour,
|
403
|
-
assert_equal 20, v.min,
|
404
|
-
assert_equal 59, v.sec,
|
405
|
-
assert_equal 123456, v.usec,
|
406
|
-
assert_equal 123456700, v.nsec,
|
407
|
-
assert_equal -28800, v.utc_offset, 'Offset'
|
399
|
+
assert_equal 1984, v.year, 'Year'
|
400
|
+
assert_equal 1, v.month, 'Month'
|
401
|
+
assert_equal 24, v.day, 'Day'
|
402
|
+
assert_equal 4, v.hour, 'Hour'
|
403
|
+
assert_equal 20, v.min, 'Minute'
|
404
|
+
assert_equal 59, v.sec, 'Second'
|
405
|
+
assert_equal 123456, v.usec, 'Microseconds'
|
406
|
+
assert_equal 123456700, v.nsec, 'Nanoseconds'
|
407
|
+
assert_equal (-28800), v.utc_offset, 'Offset'
|
408
408
|
}
|
409
409
|
assertions.call
|
410
410
|
v = find_value 84, :datetimeoffset_7, timezone: :local
|
data/test/test_helper.rb
CHANGED
@@ -93,7 +93,7 @@ module TinyTds
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def assert_client_works(client)
|
96
|
-
client.execute("SELECT 'client_works' as [client_works]").each.must_equal [{'client_works' => 'client_works'}]
|
96
|
+
_(client.execute("SELECT 'client_works' as [client_works]").each).must_equal [{'client_works' => 'client_works'}]
|
97
97
|
end
|
98
98
|
|
99
99
|
def assert_new_connections_work
|
@@ -153,6 +153,8 @@ module TinyTds
|
|
153
153
|
loader.execute(drop_sql).do
|
154
154
|
loader.execute(schema_sql).do
|
155
155
|
loader.execute(sp_sql).do
|
156
|
+
loader.execute(sp_error_sql).do
|
157
|
+
loader.execute(sp_several_prints_sql).do
|
156
158
|
loader.close
|
157
159
|
true
|
158
160
|
end
|
@@ -167,7 +169,16 @@ module TinyTds
|
|
167
169
|
) DROP TABLE datatypes
|
168
170
|
IF EXISTS(
|
169
171
|
SELECT 1 FROM sysobjects WHERE type = 'P' AND name = 'tinytds_TestReturnCodes'
|
170
|
-
) DROP PROCEDURE tinytds_TestReturnCodes
|
172
|
+
) DROP PROCEDURE tinytds_TestReturnCodes
|
173
|
+
IF EXISTS(
|
174
|
+
SELECT 1 FROM sysobjects WHERE type = 'P' AND name = 'tinytds_TestPrintWithError'
|
175
|
+
) DROP PROCEDURE tinytds_TestPrintWithError
|
176
|
+
IF EXISTS(
|
177
|
+
SELECT 1 FROM sysobjects WHERE type = 'P' AND name = 'tinytds_TestPrintWithError'
|
178
|
+
) DROP PROCEDURE tinytds_TestPrintWithError
|
179
|
+
IF EXISTS(
|
180
|
+
SELECT 1 FROM sysobjects WHERE type = 'P' AND name = 'tinytds_TestSeveralPrints'
|
181
|
+
) DROP PROCEDURE tinytds_TestSeveralPrints|
|
171
182
|
end
|
172
183
|
|
173
184
|
def drop_sql_microsoft
|
@@ -181,7 +192,15 @@ module TinyTds
|
|
181
192
|
IF EXISTS (
|
182
193
|
SELECT name FROM sysobjects
|
183
194
|
WHERE name = 'tinytds_TestReturnCodes' AND type = 'P'
|
184
|
-
) DROP PROCEDURE tinytds_TestReturnCodes
|
195
|
+
) DROP PROCEDURE tinytds_TestReturnCodes
|
196
|
+
IF EXISTS (
|
197
|
+
SELECT name FROM sysobjects
|
198
|
+
WHERE name = 'tinytds_TestPrintWithError' AND type = 'P'
|
199
|
+
) DROP PROCEDURE tinytds_TestPrintWithError
|
200
|
+
IF EXISTS (
|
201
|
+
SELECT name FROM sysobjects
|
202
|
+
WHERE name = 'tinytds_TestSeveralPrints' AND type = 'P'
|
203
|
+
) DROP PROCEDURE tinytds_TestSeveralPrints|
|
185
204
|
end
|
186
205
|
|
187
206
|
def sp_sql
|
@@ -191,6 +210,21 @@ module TinyTds
|
|
191
210
|
RETURN(420) |
|
192
211
|
end
|
193
212
|
|
213
|
+
def sp_error_sql
|
214
|
+
%|CREATE PROCEDURE tinytds_TestPrintWithError
|
215
|
+
AS
|
216
|
+
PRINT 'hello'
|
217
|
+
RAISERROR('Error following print', 16, 1)|
|
218
|
+
end
|
219
|
+
|
220
|
+
def sp_several_prints_sql
|
221
|
+
%|CREATE PROCEDURE tinytds_TestSeveralPrints
|
222
|
+
AS
|
223
|
+
PRINT 'hello 1'
|
224
|
+
PRINT 'hello 2'
|
225
|
+
PRINT 'hello 3'|
|
226
|
+
end
|
227
|
+
|
194
228
|
def find_value(id, column, query_options={})
|
195
229
|
query_options[:timezone] ||= :utc
|
196
230
|
sql = "SELECT [#{column}] FROM [datatypes] WHERE [id] = #{id}"
|
@@ -212,6 +246,9 @@ module TinyTds
|
|
212
246
|
client.execute("ROLLBACK TRANSACTION").do
|
213
247
|
end
|
214
248
|
|
249
|
+
def docker_container(cmd, wait_for: 0)
|
250
|
+
system("docker #{cmd} $(docker ps --format '{{.Names}}' --filter 'ancestor=metaskills/mssql-server-linux-tinytds:2017-GA') > /dev/null")
|
251
|
+
sleep(wait_for) if wait_for > 0
|
252
|
+
end
|
215
253
|
end
|
216
254
|
end
|
217
|
-
|
data/test/thread_test.rb
CHANGED
@@ -49,7 +49,7 @@ class ThreadTest < TinyTds::TestCase
|
|
49
49
|
begin
|
50
50
|
result = client.execute "select dbname()"
|
51
51
|
result.each { |r| puts r }
|
52
|
-
rescue Exception =>
|
52
|
+
rescue Exception => _e
|
53
53
|
# We are throwing an error on purpose here since 0.6.1 would
|
54
54
|
# segfault on errors thrown in threads
|
55
55
|
end
|
data/tiny_tds.gemspec
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.4.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: mini_portile2
|
@@ -191,12 +191,34 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
191
|
version: 2.0.0
|
192
192
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
193
|
requirements:
|
194
|
-
- - "
|
194
|
+
- - ">"
|
195
195
|
- !ruby/object:Gem::Version
|
196
|
-
version:
|
196
|
+
version: 1.3.1
|
197
197
|
requirements: []
|
198
198
|
rubygems_version: 3.0.3
|
199
199
|
signing_key:
|
200
200
|
specification_version: 4
|
201
201
|
summary: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
202
|
-
test_files:
|
202
|
+
test_files:
|
203
|
+
- test/appveyor/dbsetup.ps1
|
204
|
+
- test/appveyor/dbsetup.sql
|
205
|
+
- test/benchmark/query.rb
|
206
|
+
- test/benchmark/query_odbc.rb
|
207
|
+
- test/benchmark/query_tinytds.rb
|
208
|
+
- test/bin/install-freetds.sh
|
209
|
+
- test/bin/install-openssl.sh
|
210
|
+
- test/bin/setup.sh
|
211
|
+
- test/client_test.rb
|
212
|
+
- test/gem_test.rb
|
213
|
+
- test/result_test.rb
|
214
|
+
- test/schema/1px.gif
|
215
|
+
- test/schema/sqlserver_2000.sql
|
216
|
+
- test/schema/sqlserver_2005.sql
|
217
|
+
- test/schema/sqlserver_2008.sql
|
218
|
+
- test/schema/sqlserver_2014.sql
|
219
|
+
- test/schema/sqlserver_2016.sql
|
220
|
+
- test/schema/sqlserver_azure.sql
|
221
|
+
- test/schema/sybase_ase.sql
|
222
|
+
- test/schema_test.rb
|
223
|
+
- test/test_helper.rb
|
224
|
+
- test/thread_test.rb
|