tiny_tds 2.1.0-x64-mingw32 → 2.1.4.pre2-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +5 -4
- data/CHANGELOG.md +27 -1
- data/ISSUE_TEMPLATE.md +32 -6
- data/README.md +32 -21
- data/VERSION +1 -1
- data/appveyor.yml +26 -7
- data/docker-compose.yml +22 -0
- data/ext/tiny_tds/client.c +95 -50
- data/ext/tiny_tds/client.h +6 -3
- data/ext/tiny_tds/extconf.rb +17 -13
- data/ext/tiny_tds/extconsts.rb +2 -2
- data/ext/tiny_tds/result.c +29 -16
- data/tasks/native_gem.rake +1 -1
- data/tasks/ports.rake +6 -8
- data/tasks/ports/openssl.rb +2 -18
- data/test/bin/setup.sh +1 -1
- data/test/client_test.rb +84 -57
- data/test/gem_test.rb +15 -15
- data/test/result_test.rb +83 -42
- data/test/schema_test.rb +22 -22
- data/test/test_helper.rb +59 -5
- data/test/thread_test.rb +1 -1
- data/tiny_tds.gemspec +3 -2
- metadata +50 -39
- data/BACKERS.md +0 -32
- data/circle.yml +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a33a28cbb91241932396a3f039b62ad3d2934853ab55b58925cff0462f051777
|
4
|
+
data.tar.gz: 512f9e8ea1728b77606a8ea40e0d494af9d5ced2793c34d9d898932caa23b54c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9947a953f6a20512edc3a9045c70a87827da0143fecd73b2acf0320ae42bf043a11e6ccaa581ff78dde1980abfe8b8da9d6b8f72b76b6eac1813dbfa9eea857
|
7
|
+
data.tar.gz: 727ffa945c0ad7874016cfc481743015f7360126cabb87720ddf4eab1f6bb66894edb38746d22dcf2e35e729ed26a2d26707194d91d1bd3f4da1a96756e5a446
|
data/.travis.yml
CHANGED
@@ -8,14 +8,15 @@ env:
|
|
8
8
|
- TESTOPTS="-v"
|
9
9
|
- TINYTDS_UNIT_HOST=localhost
|
10
10
|
rvm:
|
11
|
-
- 2.
|
12
|
-
- 2.
|
13
|
-
- 2.
|
11
|
+
- 2.4.5
|
12
|
+
- 2.5.3
|
13
|
+
- 2.6.1
|
14
|
+
- 2.7.0
|
14
15
|
before_install:
|
15
16
|
- docker info
|
17
|
+
- docker-compose up -d
|
16
18
|
- sudo ./test/bin/install-openssl.sh
|
17
19
|
- sudo ./test/bin/install-freetds.sh
|
18
|
-
- sudo ./test/bin/setup.sh
|
19
20
|
install:
|
20
21
|
- gem install bundler
|
21
22
|
- bundle --version
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
## (unreleased)
|
2
|
+
|
3
|
+
## 2.1.4
|
4
|
+
|
5
|
+
* Raise error if client is unable to execute statement
|
6
|
+
* Improve handling of network related timeouts
|
7
|
+
* Fix error reporting when preceeded by info message
|
8
|
+
|
9
|
+
## 2.1.3
|
10
|
+
|
11
|
+
* Removed old/unused appveyor config
|
12
|
+
* Remove old Rubies from CI & cross compile list
|
13
|
+
* Add Ruby 2.6 and 2.7 to the cross compile list
|
14
|
+
|
15
|
+
## 2.1.2
|
16
|
+
|
17
|
+
* Use Kernel.BigDecimal vs BigDecimal.new. Fixes #409.
|
18
|
+
* Change `DBSETUTF16` abscence warning message. Fixes #410.
|
19
|
+
* Add Windows binary for Ruby-2.5. Fixes #408.
|
20
|
+
|
21
|
+
## 2.1.1
|
22
|
+
|
23
|
+
* Move message_handler from a shared value to userdata.
|
24
|
+
|
25
|
+
|
1
26
|
## 2.1.0
|
2
27
|
|
3
28
|
* Support RubyInstaller2 for Windows. Fixes #365.
|
@@ -196,6 +221,8 @@ Use both dbsetversion() vs. dbsetlversion. Partially reverts #62.
|
|
196
221
|
state of the client and the need to use Result#cancel to stop processing active results. It is also
|
197
222
|
safe to call Result#cancel over and over again.
|
198
223
|
* Look for the syb headers only.
|
224
|
+
* Fix minitest global matchers warnings.
|
225
|
+
* Fix test warnings.
|
199
226
|
|
200
227
|
|
201
228
|
## 0.3.2
|
@@ -241,4 +268,3 @@ Use both dbsetversion() vs. dbsetlversion. Partially reverts #62.
|
|
241
268
|
|
242
269
|
|
243
270
|
## 0.1.0 Initial release!
|
244
|
-
|
data/ISSUE_TEMPLATE.md
CHANGED
@@ -1,12 +1,38 @@
|
|
1
|
-
|
1
|
+
## Before submitting an issue please check these first!
|
2
2
|
|
3
|
-
*
|
3
|
+
* On Windows? If so, do you need devkit for your ruby install?
|
4
|
+
* Using Ubuntu? If so, you may have forgotten to install FreeTDS first.
|
4
5
|
* Are you using FreeTDS 0.95.80 or later? Check `$ tsql -C` to find out.
|
5
6
|
* If not, please update then uninstall the TinyTDS gem and re-install it.
|
6
|
-
*
|
7
|
+
* Have you made sure to [enable SQL Server authentication](http://bit.ly/1Kw3set)?
|
7
8
|
* Doing work with threads and the raw client? Use the ConnectionPool gem?
|
8
9
|
|
9
|
-
If none of these help. Please
|
10
|
+
If none of these help. Please fill out the following:
|
11
|
+
|
12
|
+
## Environment
|
13
|
+
|
14
|
+
**Operating System**
|
15
|
+
|
16
|
+
Please describe your operating system and version here.
|
17
|
+
If unsure please try the following from the command line:
|
18
|
+
|
19
|
+
* For Windows: `systeminfo | findstr /C:OS`
|
20
|
+
* For Linux: `lsb_release -a; uname -a`
|
21
|
+
* For Mac OSX: `sw_vers`
|
22
|
+
|
23
|
+
**TinyTDS Version and Information**
|
24
|
+
|
25
|
+
```
|
26
|
+
Please paste the full output of `ttds-tsql -C` (or `tsql -C` for older versions
|
27
|
+
of TinyTDS) here. If TinyTDS does not install, please provide the gem version.
|
28
|
+
```
|
29
|
+
|
30
|
+
|
31
|
+
**FreeTDS Version**
|
32
|
+
|
33
|
+
Please provide your system's FreeTDS version. If you are using the pre-compiled
|
34
|
+
windows gem you may omit this section.
|
35
|
+
|
36
|
+
## Description
|
10
37
|
|
11
|
-
|
12
|
-
* What version of FreeTDS you are using.
|
38
|
+
Please describe the bug or feature request here.
|
data/README.md
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
# TinyTDS - Simple and fast FreeTDS bindings for Ruby using DB-Library.
|
2
2
|
|
3
3
|
* [![TravisCI](https://travis-ci.org/rails-sqlserver/tiny_tds.svg?branch=master)](https://travis-ci.org/rails-sqlserver/tiny_tds) - TravisCI
|
4
|
-
* [![CircleCI](https://circleci.com/gh/rails-sqlserver/tiny_tds/tree/master.svg?style=svg)](https://circleci.com/gh/rails-sqlserver/tiny_tds/tree/master) - CircleCI
|
5
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
|
6
|
-
* [![Code Climate](https://codeclimate.com/github/rails-sqlserver/tiny_tds/badges/gpa.svg)](https://codeclimate.com/github/rails-sqlserver/tiny_tds) - Code Climate
|
7
5
|
* [![Gem Version](https://img.shields.io/gem/v/tiny_tds.svg)](https://rubygems.org/gems/tiny_tds) - Gem Version
|
8
|
-
* [![Dependency Status](https://dependencyci.com/github/rails-sqlserver/tiny_tds/badge)](https://dependencyci.com/github/rails-sqlserver/tiny_tds) - Dependency Status
|
9
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
|
10
7
|
|
11
|
-
## Supporting TinyTDS/Adapter
|
12
|
-
|
13
|
-
Both TinyTDS and the Rails SQL Server Adapter are MIT-licensed open source projects. Its ongoing development is made possible thanks to the support by these awesome [backers](https://github.com/rails-sqlserver/tiny_tds/blob/master/BACKERS.md). If you'd like to join them, check out our [Patreon Campaign](https://www.patreon.com/metaskills).
|
14
|
-
|
15
8
|
|
16
9
|
## About TinyTDS
|
17
10
|
|
@@ -40,19 +33,19 @@ If you're using RubyInstaller the binary gem will require that devkit is install
|
|
40
33
|
On all other platforms, we will find these dependencies. It is recommended that you install the latest FreeTDS via your method of choice. For example, here is how to install FreeTDS on Ubuntu. You might also need the `build-essential` and possibly the `libc6-dev` packages.
|
41
34
|
|
42
35
|
```shell
|
43
|
-
$ apt-get wget
|
36
|
+
$ apt-get install wget
|
44
37
|
$ apt-get install build-essential
|
45
38
|
$ apt-get install libc6-dev
|
46
39
|
|
47
|
-
$ wget http://www.freetds.org/files/stable/freetds-1.
|
48
|
-
$ tar -xzf freetds-1.
|
49
|
-
$ cd freetds-1.
|
40
|
+
$ wget http://www.freetds.org/files/stable/freetds-1.1.24.tar.gz
|
41
|
+
$ tar -xzf freetds-1.1.24.tar.gz
|
42
|
+
$ cd freetds-1.1.24
|
50
43
|
$ ./configure --prefix=/usr/local --with-tdsver=7.3
|
51
44
|
$ make
|
52
45
|
$ make install
|
53
46
|
```
|
54
47
|
|
55
|
-
|
48
|
+
Please read the MiniPortile and/or Windows sections at the end of this file for advanced configuration options past the following:
|
56
49
|
|
57
50
|
```
|
58
51
|
--with-freetds-dir=DIR
|
@@ -75,11 +68,11 @@ TinyTDS is developed against FreeTDS 0.95, 0.99, and 1.0 current. Our default an
|
|
75
68
|
|
76
69
|
**NOTE:** Windows users of our pre-compiled native gems need not worry about installing FreeTDS and its dependencies.
|
77
70
|
|
78
|
-
* **Do I need to install FreeTDS?** Yes! Somehow, someway, you are going to need FreeTDS for TinyTDS to compile against.
|
71
|
+
* **Do I need to install FreeTDS?** Yes! Somehow, someway, you are going to need FreeTDS for TinyTDS to compile against.
|
79
72
|
|
80
73
|
* **OK, I am installing FreeTDS, how do I configure it?** Contrary to what most people think, you do not need to specially configure FreeTDS in any way for client libraries like TinyTDS to use it. About the only requirement is that you compile it with libiconv for proper encoding support. FreeTDS must also be compiled with OpenSSL (or the like) to use it with Azure. See the "Using TinyTDS with Azure" section below for more info.
|
81
74
|
|
82
|
-
* **Do I need to configure `--with-tdsver` equal to anything?** Most likely! Technically you should not have
|
75
|
+
* **Do I need to configure `--with-tdsver` equal to anything?** Most likely! Technically you should not have to. This is only a default for clients/configs that do not specify what TDS version they want to use. We are currently having issues with passing down a TDS version with the login bit. Till we get that fixed, if you are not using a freetds.conf or a TDSVER environment variable, then make sure to use 7.1.
|
83
76
|
|
84
77
|
* **But I want to use TDS version 7.2 for SQL Server 2005 and up!** TinyTDS uses TDS version 7.1 (previously named 8.0) and fully supports all the data types supported by FreeTDS, this includes `varchar(max)` and `nvarchar(max)`. Technically compiling and using TDS version 7.2 with FreeTDS is not supported. But this does not mean those data types will not work. I know, it's confusing If you want to learn more, read this thread. http://lists.ibiblio.org/pipermail/freetds/2011q3/027306.html
|
85
78
|
|
@@ -117,7 +110,7 @@ Creating a new client takes a hash of options. For valid iconv encoding options,
|
|
117
110
|
* :appname - Short string seen in SQL Servers process/activity window.
|
118
111
|
* :tds_version - TDS version. Defaults to "7.3".
|
119
112
|
* :login_timeout - Seconds to wait for login. Default to 60 seconds.
|
120
|
-
* :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).
|
121
114
|
* :encoding - Any valid iconv value like CP1251 or ISO-8859-1. Default UTF-8.
|
122
115
|
* :azure - Pass true to signal that you are connecting to azure.
|
123
116
|
* :contained - Pass true to signal that you are connecting with a contained database user.
|
@@ -329,9 +322,13 @@ By default row caching is turned on because the SQL Server adapter for ActiveRec
|
|
329
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.
|
330
323
|
|
331
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
|
+
|
332
329
|
## Binstubs
|
333
330
|
|
334
|
-
The TinyTDS gem uses binstub wrappers which mirror compiled [FreeTDS Utilities](
|
331
|
+
The TinyTDS gem uses binstub wrappers which mirror compiled [FreeTDS Utilities](https://www.freetds.org/userguide/usefreetds.html) 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.
|
335
332
|
|
336
333
|
* tsql - Used to test connections and debug compile time settings.
|
337
334
|
* defncopy - Used to dump schema structures.
|
@@ -407,7 +404,7 @@ The default is true and since FreeTDS v1.0 would do this as well.
|
|
407
404
|
|
408
405
|
## Compiling Gems for Windows
|
409
406
|
|
410
|
-
For the convenience of Windows users, TinyTDS ships pre-compiled gems for
|
407
|
+
For the convenience of Windows users, TinyTDS ships pre-compiled gems for supported versions of Ruby on Windows. In order to generate these gems, [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock) is used. This project provides several [Docker images](https://registry.hub.docker.com/u/larskanis/) with rvm, cross-compilers and a number of different target versions of Ruby.
|
411
408
|
|
412
409
|
Run the following rake task to compile the gems for Windows. This will check the availability of [Docker](https://www.docker.com/) (and boot2docker on Windows or OS-X) and will give some advice for download and installation. When docker is running, it will download the docker image (once-only) and start the build:
|
413
410
|
|
@@ -426,17 +423,20 @@ First, clone the repo using the command line or your Git GUI of choice.
|
|
426
423
|
$ git clone git@github.com:rails-sqlserver/tiny_tds.git
|
427
424
|
```
|
428
425
|
|
429
|
-
After that, the quickest way to get setup for development is to use [Docker](https://www.docker.com/). Assuming you have [downloaded docker](https://www.docker.com/products/docker) for your platform
|
426
|
+
After that, the quickest way to get setup for development is to use [Docker](https://www.docker.com/). Assuming you have [downloaded docker](https://www.docker.com/products/docker) for your platform, you can use [docker-compose](https://docs.docker.com/compose/install/) to run the necessary containers for testing.
|
430
427
|
|
431
428
|
```shell
|
432
|
-
$
|
429
|
+
$ docker-compose up -d
|
433
430
|
```
|
434
431
|
|
435
|
-
This will download our SQL Server for Linux Docker image based from [microsoft/mssql-server-linux/](https://hub.docker.com/r/microsoft/mssql-server-linux/). Our image already has the `[tinytdstest]` DB and `tinytds` users created. Basically, it does the following.
|
432
|
+
This will download our SQL Server for Linux Docker image based from [microsoft/mssql-server-linux/](https://hub.docker.com/r/microsoft/mssql-server-linux/). Our image already has the `[tinytdstest]` DB and `tinytds` users created. This will also download a [toxiproxy](https://github.com/shopify/toxiproxy) Docker image which we can use to simulate network failures for tests. Basically, it does the following.
|
436
433
|
|
437
434
|
```shell
|
435
|
+
$ docker network create main-network
|
438
436
|
$ docker pull metaskills/mssql-server-linux-tinytds
|
439
|
-
$ docker run -p 1433:1433 -d metaskills/mssql-server-linux-tinytds
|
437
|
+
$ docker run -p 1433:1433 -d --name sqlserver --network main-network metaskills/mssql-server-linux-tinytds
|
438
|
+
$ docker pull shopify/toxiproxy
|
439
|
+
$ docker run -p 8474:8474 -p 1234:1234 -d --name toxiproxy --network main-network shopify/toxiproxy
|
440
440
|
```
|
441
441
|
|
442
442
|
If you are using your own database. Make sure to run these SQL commands as SA to get the test database and user installed.
|
@@ -468,6 +468,17 @@ $ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_SCHEMA=sqlserver_azure
|
|
468
468
|
$ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_UNIT_PORT=5000 TINYTDS_SCHEMA=sybase_ase
|
469
469
|
```
|
470
470
|
|
471
|
+
## Docker Builds
|
472
|
+
|
473
|
+
If you use a [multi stage](https://docs.docker.com/develop/develop-images/multistage-build/) Docker build to assemble your gems in one phase and then copy your app and gems
|
474
|
+
into another, lighter, container without build tools you will need to make sure you tell the OS how to find dependencies for TinyTDS.
|
475
|
+
|
476
|
+
After you have built and installed FreeTDS it will normally place library files in `/usr/local/lib`. When TinyTDS builds native extensions,
|
477
|
+
it [already knows to look here](https://github.com/rails-sqlserver/tiny_tds/blob/master/ext/tiny_tds/extconf.rb#L31) but if you copy your app to a new container that link will be broken.
|
478
|
+
|
479
|
+
Set the LD_LIBRARY_PATH environment variable `export LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}` and run `ldconfig`. If you run `ldd tiny_tds.so` you should not see any broken links. Make
|
480
|
+
sure you also copied in the library dependencies from your build container with a command like `COPY --from=builder /usr/local/lib /usr/local/lib`.
|
481
|
+
|
471
482
|
## Help & Support
|
472
483
|
|
473
484
|
* Github Source: http://github.com/rails-sqlserver/tiny_tds
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.4.pre2
|
data/appveyor.yml
CHANGED
@@ -1,21 +1,39 @@
|
|
1
1
|
init:
|
2
2
|
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
3
|
-
- SET PATH=C:\MinGW\msys\1.0\bin;%PATH%
|
4
3
|
- SET RAKEOPT=-rdevkit
|
5
4
|
- SET TESTOPTS='-v'
|
6
|
-
- SET MAKE=make V=1
|
5
|
+
- SET MAKE=make V=1 -j2
|
7
6
|
clone_depth: 5
|
8
7
|
skip_tags: true
|
9
8
|
skip_branch_with_pr: true
|
10
9
|
matrix:
|
11
|
-
fast_finish:
|
10
|
+
fast_finish: false
|
12
11
|
install:
|
13
12
|
# Output debugging info
|
14
13
|
- ps: Update-AppveyorBuild -Version "$(Get-Content $env:appveyor_build_folder\VERSION).$env:appveyor_build_number"
|
14
|
+
- ps: |
|
15
|
+
if ($env:ruby_version -like "*head*") {
|
16
|
+
$(new-object net.webclient).DownloadFile("https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-$env:ruby_version.exe", "$pwd/ruby-setup.exe")
|
17
|
+
cmd /c ruby-setup.exe /verysilent /dir=C:/Ruby$env:ruby_version
|
18
|
+
}
|
15
19
|
- perl --version
|
16
20
|
- ruby --version
|
17
21
|
- gem --version
|
18
|
-
|
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"
|
35
|
+
# prevent freetds to link to wrong ws2_32 lib on i686-w64-mingw32
|
36
|
+
- c:/msys64/usr/bin/rm /usr/lib/w32api/libws2_32.a
|
19
37
|
# Set up project prerequisits
|
20
38
|
- bundle install
|
21
39
|
- bundle exec rake ports
|
@@ -43,9 +61,10 @@ environment:
|
|
43
61
|
TINYTDS_UNIT_AZURE_PASS:
|
44
62
|
secure: fYKSKV4v+36OFQp2nZdX4DfUpgmy5cm0wuR73cgdmEk=
|
45
63
|
matrix:
|
46
|
-
- ruby_version: "24-x64"
|
47
64
|
- ruby_version: "24"
|
48
|
-
- ruby_version: "
|
49
|
-
- ruby_version: "
|
65
|
+
- ruby_version: "25-x64"
|
66
|
+
- ruby_version: "26"
|
67
|
+
- ruby_version: "head-x64"
|
50
68
|
on_failure:
|
69
|
+
- find -name config.log | xargs cat
|
51
70
|
- find -name compile.log | xargs cat
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
version: '3'
|
2
|
+
|
3
|
+
networks:
|
4
|
+
main-network:
|
5
|
+
|
6
|
+
services:
|
7
|
+
mssql:
|
8
|
+
image: metaskills/mssql-server-linux-tinytds:2017-GA
|
9
|
+
container_name: sqlserver
|
10
|
+
ports:
|
11
|
+
- "1433:1433"
|
12
|
+
networks:
|
13
|
+
- main-network
|
14
|
+
|
15
|
+
toxiproxy:
|
16
|
+
image: shopify/toxiproxy
|
17
|
+
container_name: toxiproxy
|
18
|
+
ports:
|
19
|
+
- "8474:8474"
|
20
|
+
- "1234:1234"
|
21
|
+
networks:
|
22
|
+
- main-network
|
data/ext/tiny_tds/client.c
CHANGED
@@ -7,7 +7,6 @@ static ID sym_username, sym_password, sym_dataserver, sym_database, sym_appname,
|
|
7
7
|
static ID intern_source_eql, intern_severity_eql, intern_db_error_number_eql, intern_os_error_number_eql;
|
8
8
|
static ID intern_new, intern_dup, intern_transpose_iconv_encoding, intern_local_offset, intern_gsub, intern_call;
|
9
9
|
VALUE opt_escape_regex, opt_escape_dblquote;
|
10
|
-
VALUE message_handler;
|
11
10
|
|
12
11
|
|
13
12
|
// Lib Macros
|
@@ -25,25 +24,26 @@ VALUE message_handler;
|
|
25
24
|
|
26
25
|
// Lib Backend (Helpers)
|
27
26
|
|
28
|
-
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc,
|
27
|
+
VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, tinytds_errordata error) {
|
29
28
|
VALUE e;
|
30
29
|
GET_CLIENT_USERDATA(dbproc);
|
31
|
-
if (cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
|
30
|
+
if (error.cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
|
32
31
|
userdata->dbsqlok_sent = 1;
|
33
32
|
dbsqlok(dbproc);
|
34
33
|
userdata->dbcancel_sent = 1;
|
35
34
|
dbcancel(dbproc);
|
36
35
|
}
|
37
|
-
e = rb_exc_new2(cTinyTdsError, error);
|
38
|
-
rb_funcall(e, intern_source_eql, 1, rb_str_new2(source));
|
39
|
-
if (severity)
|
40
|
-
rb_funcall(e, intern_severity_eql, 1, INT2FIX(severity));
|
41
|
-
if (dberr)
|
42
|
-
rb_funcall(e, intern_db_error_number_eql, 1, INT2FIX(dberr));
|
43
|
-
if (oserr)
|
44
|
-
rb_funcall(e, intern_os_error_number_eql, 1, INT2FIX(oserr));
|
45
|
-
|
46
|
-
if (severity <= 10 && is_message) {
|
36
|
+
e = rb_exc_new2(cTinyTdsError, error.error);
|
37
|
+
rb_funcall(e, intern_source_eql, 1, rb_str_new2(error.source));
|
38
|
+
if (error.severity)
|
39
|
+
rb_funcall(e, intern_severity_eql, 1, INT2FIX(error.severity));
|
40
|
+
if (error.dberr)
|
41
|
+
rb_funcall(e, intern_db_error_number_eql, 1, INT2FIX(error.dberr));
|
42
|
+
if (error.oserr)
|
43
|
+
rb_funcall(e, intern_os_error_number_eql, 1, INT2FIX(error.oserr));
|
44
|
+
|
45
|
+
if (error.severity <= 10 && error.is_message) {
|
46
|
+
VALUE message_handler = userdata && userdata->message_handler ? userdata->message_handler : Qnil;
|
47
47
|
if (message_handler && message_handler != Qnil && rb_respond_to(message_handler, intern_call) != 0) {
|
48
48
|
rb_funcall(message_handler, intern_call, 1, e);
|
49
49
|
}
|
@@ -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
|
|
@@ -99,6 +115,16 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
99
115
|
break;
|
100
116
|
}
|
101
117
|
|
118
|
+
tinytds_errordata error_data = {
|
119
|
+
.is_message = 0,
|
120
|
+
.cancel = cancel,
|
121
|
+
.severity = severity,
|
122
|
+
.dberr = dberr,
|
123
|
+
.oserr = oserr
|
124
|
+
};
|
125
|
+
strncpy(error_data.error, dberrstr, ERROR_MSG_SIZE);
|
126
|
+
strncpy(error_data.source, source, ERROR_MSG_SIZE);
|
127
|
+
|
102
128
|
/*
|
103
129
|
When in non-blocking mode we need to store the exception data to throw it
|
104
130
|
once the blocking call returns, otherwise we will segfault ruby since part
|
@@ -110,27 +136,9 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
110
136
|
dbcancel(dbproc);
|
111
137
|
userdata->dbcancel_sent = 1;
|
112
138
|
}
|
113
|
-
|
114
|
-
/*
|
115
|
-
If we've already captured an error message, don't overwrite it. This is
|
116
|
-
here because FreeTDS sends a generic "General SQL Server error" message
|
117
|
-
that will overwrite the real message. This is not normally a problem
|
118
|
-
because a ruby exception is normally thrown and we bail before the
|
119
|
-
generic message can be sent.
|
120
|
-
*/
|
121
|
-
if (!userdata->nonblocking_error.is_set) {
|
122
|
-
userdata->nonblocking_error.is_message = 0;
|
123
|
-
userdata->nonblocking_error.cancel = cancel;
|
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
|
-
|
139
|
+
push_userdata_error(userdata, error_data);
|
132
140
|
} else {
|
133
|
-
rb_tinytds_raise_error(dbproc,
|
141
|
+
rb_tinytds_raise_error(dbproc, error_data);
|
134
142
|
}
|
135
143
|
|
136
144
|
return return_value;
|
@@ -142,36 +150,72 @@ int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severi
|
|
142
150
|
|
143
151
|
int is_message_an_error = severity > 10 ? 1 : 0;
|
144
152
|
|
153
|
+
tinytds_errordata error_data = {
|
154
|
+
.is_message = !is_message_an_error,
|
155
|
+
.cancel = is_message_an_error,
|
156
|
+
.severity = severity,
|
157
|
+
.dberr = msgno,
|
158
|
+
.oserr = msgstate
|
159
|
+
};
|
160
|
+
strncpy(error_data.error, msgtext, ERROR_MSG_SIZE);
|
161
|
+
strncpy(error_data.source, source, ERROR_MSG_SIZE);
|
162
|
+
|
145
163
|
// See tinytds_err_handler() for info about why we do this
|
146
164
|
if (userdata && userdata->nonblocking) {
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
userdata->nonblocking_error.dberr = msgno;
|
154
|
-
userdata->nonblocking_error.oserr = msgstate;
|
155
|
-
userdata->nonblocking_error.is_set = 1;
|
156
|
-
}
|
165
|
+
/*
|
166
|
+
In the case of non-blocking command batch execution we can receive multiple messages
|
167
|
+
(including errors). We keep track of those here so they can be processed once the
|
168
|
+
non-blocking call returns.
|
169
|
+
*/
|
170
|
+
push_userdata_error(userdata, error_data);
|
157
171
|
|
158
172
|
if (is_message_an_error && !dbdead(dbproc) && !userdata->closed) {
|
159
173
|
dbcancel(dbproc);
|
160
174
|
userdata->dbcancel_sent = 1;
|
161
175
|
}
|
162
176
|
} else {
|
163
|
-
rb_tinytds_raise_error(dbproc,
|
177
|
+
rb_tinytds_raise_error(dbproc, error_data);
|
164
178
|
}
|
165
179
|
return 0;
|
166
180
|
}
|
167
181
|
|
182
|
+
/*
|
183
|
+
Used by dbsetinterrupt -
|
184
|
+
This gets called periodically while waiting on a read from the server
|
185
|
+
Right now, we only care about cases where a read from the server is
|
186
|
+
taking longer than the specified timeout and dbcancel is not working.
|
187
|
+
In these cases we decide that we actually want to handle the interrupt
|
188
|
+
*/
|
189
|
+
static int check_interrupt(void *ptr) {
|
190
|
+
GET_CLIENT_USERDATA((DBPROCESS *)ptr);
|
191
|
+
return userdata->timing_out;
|
192
|
+
}
|
193
|
+
|
194
|
+
/*
|
195
|
+
Used by dbsetinterrupt -
|
196
|
+
This gets called if check_interrupt returns TRUE.
|
197
|
+
Right now, this is only used in cases where a read from the server is
|
198
|
+
taking longer than the specified timeout and dbcancel is not working.
|
199
|
+
Return INT_CANCEL to abort the current command batch.
|
200
|
+
*/
|
201
|
+
static int handle_interrupt(void *ptr) {
|
202
|
+
GET_CLIENT_USERDATA((DBPROCESS *)ptr);
|
203
|
+
if (userdata->timing_out) {
|
204
|
+
return INT_CANCEL;
|
205
|
+
}
|
206
|
+
return INT_CONTINUE;
|
207
|
+
}
|
208
|
+
|
168
209
|
static void rb_tinytds_client_reset_userdata(tinytds_client_userdata *userdata) {
|
169
210
|
userdata->timing_out = 0;
|
170
211
|
userdata->dbsql_sent = 0;
|
171
212
|
userdata->dbsqlok_sent = 0;
|
172
213
|
userdata->dbcancel_sent = 0;
|
173
214
|
userdata->nonblocking = 0;
|
174
|
-
|
215
|
+
// the following is mainly done for consistency since the values are reset accordingly in nogvl_setup/cleanup.
|
216
|
+
// the nonblocking_errors array does not need to be freed here. That is done as part of nogvl_cleanup.
|
217
|
+
userdata->nonblocking_errors_length = 0;
|
218
|
+
userdata->nonblocking_errors_size = 0;
|
175
219
|
}
|
176
220
|
|
177
221
|
static void rb_tinytds_client_mark(void *ptr) {
|
@@ -252,8 +296,8 @@ static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
|
|
252
296
|
REQUIRE_OPEN_CLIENT(cwrap);
|
253
297
|
dbcmd(cwrap->client, StringValueCStr(sql));
|
254
298
|
if (dbsqlsend(cwrap->client) == FAIL) {
|
255
|
-
|
256
|
-
return
|
299
|
+
rb_raise(cTinyTdsError, "failed to execute statement");
|
300
|
+
return self;
|
257
301
|
}
|
258
302
|
cwrap->userdata->dbsql_sent = 1;
|
259
303
|
result = rb_tinytds_new_result_obj(cwrap);
|
@@ -322,7 +366,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
322
366
|
azure = rb_hash_aref(opts, sym_azure);
|
323
367
|
contained = rb_hash_aref(opts, sym_contained);
|
324
368
|
use_utf16 = rb_hash_aref(opts, sym_use_utf16);
|
325
|
-
message_handler = rb_hash_aref(opts, sym_message_handler);
|
369
|
+
cwrap->userdata->message_handler = rb_hash_aref(opts, sym_message_handler);
|
326
370
|
/* Dealing with options. */
|
327
371
|
if (dbinit() == FAIL) {
|
328
372
|
rb_raise(cTinyTdsError, "failed dbinit() function");
|
@@ -362,7 +406,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
362
406
|
if (use_utf16 == Qfalse) { DBSETLUTF16(cwrap->login, 0); }
|
363
407
|
#else
|
364
408
|
if (use_utf16 == Qtrue || use_utf16 == Qfalse) {
|
365
|
-
|
409
|
+
rb_warning("TinyTds: Please consider upgrading to FreeTDS 0.99 or higher for better unicode support.\n");
|
366
410
|
}
|
367
411
|
#endif
|
368
412
|
|
@@ -381,6 +425,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
381
425
|
}
|
382
426
|
}
|
383
427
|
dbsetuserdata(cwrap->client, (BYTE*)cwrap->userdata);
|
428
|
+
dbsetinterrupt(cwrap->client, check_interrupt, handle_interrupt);
|
384
429
|
cwrap->userdata->closed = 0;
|
385
430
|
if (!NIL_P(database) && (azure != Qtrue)) {
|
386
431
|
dbuse(cwrap->client, StringValueCStr(database));
|