odbc_adapter 5.0.3 → 5.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -3
- data/Dockerfile.dev +12 -0
- data/Gemfile +1 -1
- data/README.md +20 -0
- data/docker/docker-entrypoint.sh +21 -0
- data/docker/test.sh +5 -0
- data/lib/active_record/connection_adapters/odbc_adapter.rb +30 -12
- data/lib/odbc_adapter/column_metadata.rb +1 -1
- data/lib/odbc_adapter/database_metadata.rb +9 -2
- data/lib/odbc_adapter/error.rb +2 -0
- data/lib/odbc_adapter/version.rb +1 -1
- data/odbc_adapter.gemspec +5 -6
- metadata +22 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89df3abd57cdeb10fd9d90428b53d3394a8dd14c
|
4
|
+
data.tar.gz: 30144892fafcb6eae63c2a96bed10cf7f9195839
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afb573a1a3a59041ea84318b9d084a709c25016dd7c7e830941c90918a2d23fb28e8e003feadd167790dc5650a2defe2a57d9c60f69a565cc34179f3ce47e4c7
|
7
|
+
data.tar.gz: fefefa7812c4ed82f3c5b7b033f04fe91776c8a4039eddfddcdab31ad75e8be46ebf8436de63f40cf27aa86d9e95408546b1a40f33b2d82e5f04abcd2a8694d2
|
data/.rubocop.yml
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
AllCops:
|
2
2
|
DisplayCopNames: true
|
3
3
|
DisplayStyleGuide: true
|
4
|
-
TargetRubyVersion: 2.
|
4
|
+
TargetRubyVersion: 2.1
|
5
5
|
Exclude:
|
6
6
|
- 'vendor/**/*'
|
7
7
|
|
8
|
+
Lint/AmbiguousBlockAssociation:
|
9
|
+
Enabled: false
|
10
|
+
|
8
11
|
Metrics/AbcSize:
|
9
12
|
Enabled: false
|
10
13
|
|
@@ -28,5 +31,5 @@ Style/Documentation:
|
|
28
31
|
|
29
32
|
Style/PercentLiteralDelimiters:
|
30
33
|
PreferredDelimiters:
|
31
|
-
|
32
|
-
'%
|
34
|
+
default: '[]'
|
35
|
+
'%r': '{}'
|
data/Dockerfile.dev
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM ruby:2.4.0
|
2
|
+
MAINTAINER data@localytics.com
|
3
|
+
|
4
|
+
ENV DEBIAN_FRONTEND noninteractive
|
5
|
+
RUN echo "deb http://deb.debian.org/debian/ jessie main" > /etc/apt/sources.list
|
6
|
+
RUN echo "deb-src http://deb.debian.org/debian/ jessie main" >> /etc/apt/sources.list
|
7
|
+
RUN echo "deb http://security.debian.org/ jessie/updates main" >> /etc/apt/sources.list
|
8
|
+
RUN echo "deb-src http://security.debian.org/ jessie/updates main" >> /etc/apt/sources.list
|
9
|
+
RUN apt-get update && apt-get -y install libnss3-tools unixodbc-dev libmyodbc mysql-client odbc-postgresql postgresql
|
10
|
+
|
11
|
+
WORKDIR /workspace
|
12
|
+
CMD docker/docker-entrypoint.sh
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ODBCAdapter
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/localytics/odbc_adapter.svg?branch=master)](https://travis-ci.org/localytics/odbc_adapter)
|
4
|
+
[![Gem](https://img.shields.io/gem/v/odbc_adapter.svg)](https://rubygems.org/gems/odbc_adapter)
|
4
5
|
|
5
6
|
An ActiveRecord ODBC adapter. Master branch is working off of Rails 5.0.1. Previous work has been done to make it compatible with Rails 3.2 and 4.2; for those versions use the 3.2.x or 4.2.x gem releases.
|
6
7
|
|
@@ -50,6 +51,25 @@ ActiveRecord models that use this connection will now be connecting to the confi
|
|
50
51
|
|
51
52
|
To run the tests, you'll need the ODBC driver as well as the connection adapter for each database against which you're trying to test. Then run `DSN=MyDatabaseDSN bundle exec rake test` and the test suite will be run by connecting to your database.
|
52
53
|
|
54
|
+
## Testing Using a Docker Container Because ODBC on Mac is Hard
|
55
|
+
|
56
|
+
Tested on Sierra.
|
57
|
+
|
58
|
+
|
59
|
+
Run from project root:
|
60
|
+
|
61
|
+
```
|
62
|
+
bundle package
|
63
|
+
docker build -f Dockerfile.dev -t odbc-dev .
|
64
|
+
|
65
|
+
# Local mount mysql directory to avoid some permissions problems
|
66
|
+
mkdir -p /tmp/mysql
|
67
|
+
docker run -it --rm -v $(pwd):/workspace -v /tmp/mysql:/var/lib/mysql odbc-dev:latest
|
68
|
+
|
69
|
+
# In container
|
70
|
+
docker/test.sh
|
71
|
+
```
|
72
|
+
|
53
73
|
## Contributing
|
54
74
|
|
55
75
|
Bug reports and pull requests are welcome on GitHub at https://github.com/localytics/odbc_adapter.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e -x
|
3
|
+
|
4
|
+
# Installing mysql at startup due to file permissions: https://github.com/geerlingguy/drupal-vm/issues/1497
|
5
|
+
apt-get install -y mysql-server
|
6
|
+
bundle install --local
|
7
|
+
service mysql start
|
8
|
+
|
9
|
+
# Allows passwordless auth from command line and odbc
|
10
|
+
sed -i "s/local all postgres peer/local all postgres trust/" /etc/postgresql/9.4/main/pg_hba.conf
|
11
|
+
sed -i "s/host all all 127.0.0.1\/32 md5/host all all 127.0.0.1\/32 trust/" /etc/postgresql/9.4/main/pg_hba.conf
|
12
|
+
service postgresql start
|
13
|
+
|
14
|
+
odbcinst -i -d -f /usr/share/libmyodbc/odbcinst.ini
|
15
|
+
mysql -e "DROP DATABASE IF EXISTS odbc_test; CREATE DATABASE IF NOT EXISTS odbc_test;" -uroot
|
16
|
+
mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost';" -uroot
|
17
|
+
|
18
|
+
odbcinst -i -d -f /usr/share/psqlodbc/odbcinst.ini.template
|
19
|
+
psql -c "CREATE DATABASE odbc_test;" -U postgres
|
20
|
+
|
21
|
+
/bin/bash
|
data/docker/test.sh
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
echo "Testing mysql" && CONN_STR='DRIVER=MySQL;SERVER=localhost;DATABASE=odbc_test;USER=root;PASSWORD=;' bundle exec rake && \
|
4
|
+
echo "Testing postgres" && CONN_STR='DRIVER={PostgreSQL ANSI};SERVER=localhost;PORT=5432;DATABASE=odbc_test;UID=postgres;' bundle exec rake && \
|
5
|
+
echo "Testing postgres utf8" && CONN_STR='DRIVER={PostgreSQL UNICODE};SERVER=localhost;PORT=5432;DATABASE=odbc_test;UID=postgres;ENCODING=utf8' bundle exec rake
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'arel/visitors/bind_visitor'
|
3
3
|
require 'odbc'
|
4
|
+
require 'odbc_utf8'
|
4
5
|
|
5
6
|
require 'odbc_adapter/database_limits'
|
6
7
|
require 'odbc_adapter/database_statements'
|
@@ -30,7 +31,7 @@ module ActiveRecord
|
|
30
31
|
raise ArgumentError, 'No data source name (:dsn) or connection string (:conn_str) specified.'
|
31
32
|
end
|
32
33
|
|
33
|
-
database_metadata = ::ODBCAdapter::DatabaseMetadata.new(connection)
|
34
|
+
database_metadata = ::ODBCAdapter::DatabaseMetadata.new(connection, config[:encoding_bug])
|
34
35
|
database_metadata.adapter_class.new(connection, logger, config, database_metadata)
|
35
36
|
end
|
36
37
|
|
@@ -40,8 +41,11 @@ module ActiveRecord
|
|
40
41
|
def odbc_dsn_connection(config)
|
41
42
|
username = config[:username] ? config[:username].to_s : nil
|
42
43
|
password = config[:password] ? config[:password].to_s : nil
|
43
|
-
|
44
|
-
|
44
|
+
odbc_module = config[:encoding] == 'utf8' ? ODBC_UTF8 : ODBC
|
45
|
+
connection = odbc_module.connect(config[:dsn], username, password)
|
46
|
+
|
47
|
+
# encoding_bug indicates that the driver is using non ASCII and has the issue referenced here https://github.com/larskanis/ruby-odbc/issues/2
|
48
|
+
[connection, config.merge(username: username, password: password, encoding_bug: config[:encoding] == 'utf8')]
|
45
49
|
end
|
46
50
|
|
47
51
|
# Connect using ODBC connection string
|
@@ -49,12 +53,15 @@ module ActiveRecord
|
|
49
53
|
# e.g. "DSN=virt5;UID=rails;PWD=rails"
|
50
54
|
# "DRIVER={OpenLink Virtuoso};HOST=carlmbp;UID=rails;PWD=rails"
|
51
55
|
def odbc_conn_str_connection(config)
|
52
|
-
|
56
|
+
attrs = config[:conn_str].split(';').map { |option| option.split('=', 2) }.to_h
|
57
|
+
odbc_module = attrs['ENCODING'] == 'utf8' ? ODBC_UTF8 : ODBC
|
58
|
+
driver = odbc_module::Driver.new
|
53
59
|
driver.name = 'odbc'
|
54
|
-
driver.attrs =
|
60
|
+
driver.attrs = attrs
|
55
61
|
|
56
|
-
connection =
|
57
|
-
|
62
|
+
connection = odbc_module::Database.new.drvconnect(driver)
|
63
|
+
# encoding_bug indicates that the driver is using non ASCII and has the issue referenced here https://github.com/larskanis/ruby-odbc/issues/2
|
64
|
+
[connection, config.merge(driver: driver, encoding: attrs['ENCODING'], encoding_bug: attrs['ENCODING'] == 'utf8')]
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
@@ -69,9 +76,11 @@ module ActiveRecord
|
|
69
76
|
ADAPTER_NAME = 'ODBC'.freeze
|
70
77
|
BOOLEAN_TYPE = 'BOOLEAN'.freeze
|
71
78
|
|
72
|
-
ERR_DUPLICATE_KEY_VALUE
|
73
|
-
ERR_QUERY_TIMED_OUT
|
74
|
-
ERR_QUERY_TIMED_OUT_MESSAGE
|
79
|
+
ERR_DUPLICATE_KEY_VALUE = 23_505
|
80
|
+
ERR_QUERY_TIMED_OUT = 57_014
|
81
|
+
ERR_QUERY_TIMED_OUT_MESSAGE = /Query has timed out/
|
82
|
+
ERR_CONNECTION_FAILED_REGEX = '^08[0S]0[12347]'.freeze
|
83
|
+
ERR_CONNECTION_FAILED_MESSAGE = /Client connection failed/
|
75
84
|
|
76
85
|
# The object that stores the information that is fetched from the DBMS
|
77
86
|
# when a connection is first established.
|
@@ -107,11 +116,12 @@ module ActiveRecord
|
|
107
116
|
# new connection with the database.
|
108
117
|
def reconnect!
|
109
118
|
disconnect!
|
119
|
+
odbc_module = @config[:encoding] == 'utf8' ? ODBC_UTF8 : ODBC
|
110
120
|
@connection =
|
111
121
|
if @config.key?(:dsn)
|
112
|
-
|
122
|
+
odbc_module.connect(@config[:dsn], @config[:username], @config[:password])
|
113
123
|
else
|
114
|
-
|
124
|
+
odbc_module::Database.new.drvconnect(@config[:driver])
|
115
125
|
end
|
116
126
|
configure_time_options(@connection)
|
117
127
|
super
|
@@ -134,6 +144,7 @@ module ActiveRecord
|
|
134
144
|
protected
|
135
145
|
|
136
146
|
# Build the type map for ActiveRecord
|
147
|
+
# Here, ODBC and ODBC_UTF8 constants are interchangeable
|
137
148
|
def initialize_type_map(map)
|
138
149
|
map.register_type 'boolean', Type::Boolean.new
|
139
150
|
map.register_type ODBC::SQL_CHAR, Type::String.new
|
@@ -175,6 +186,13 @@ module ActiveRecord
|
|
175
186
|
ActiveRecord::RecordNotUnique.new(message, exception)
|
176
187
|
elsif error_number == ERR_QUERY_TIMED_OUT || exception.message =~ ERR_QUERY_TIMED_OUT_MESSAGE
|
177
188
|
::ODBCAdapter::QueryTimeoutError.new(message, exception)
|
189
|
+
elsif exception.message.match(ERR_CONNECTION_FAILED_REGEX) || exception.message =~ ERR_CONNECTION_FAILED_MESSAGE
|
190
|
+
begin
|
191
|
+
reconnect!
|
192
|
+
::ODBCAdapter::ConnectionFailedError.new(message, exception)
|
193
|
+
rescue => e
|
194
|
+
puts "unable to reconnect #{e}"
|
195
|
+
end
|
178
196
|
else
|
179
197
|
super
|
180
198
|
end
|
@@ -50,7 +50,7 @@ module ODBCAdapter
|
|
50
50
|
# how closely the native type maps to that SQL type.
|
51
51
|
# But, for :text and :binary, select the native type with the
|
52
52
|
# largest capacity. (Compare SQLGetTypeInfo:COLUMN_SIZE values)
|
53
|
-
selected_row = rows.max_by { |row| row[2] } if [
|
53
|
+
selected_row = rows.max_by { |row| row[2] } if %i[text binary].include?(abstract)
|
54
54
|
result = { name: selected_row[0] } # SQLGetTypeInfo: TYPE_NAME
|
55
55
|
|
56
56
|
create_params = selected_row[5]
|
@@ -15,8 +15,15 @@ module ODBCAdapter
|
|
15
15
|
|
16
16
|
attr_reader :values
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
# has_encoding_bug refers to https://github.com/larskanis/ruby-odbc/issues/2 where ruby-odbc in UTF8 mode
|
19
|
+
# returns incorrectly encoded responses to getInfo
|
20
|
+
def initialize(connection, has_encoding_bug = false)
|
21
|
+
@values = Hash[FIELDS.map do |field|
|
22
|
+
info = connection.get_info(ODBC.const_get(field))
|
23
|
+
info = info.encode(Encoding.default_external, 'UTF-16LE') if info.is_a?(String) && has_encoding_bug
|
24
|
+
|
25
|
+
[field, info]
|
26
|
+
end]
|
20
27
|
end
|
21
28
|
|
22
29
|
def adapter_class
|
data/lib/odbc_adapter/error.rb
CHANGED
data/lib/odbc_adapter/version.rb
CHANGED
data/odbc_adapter.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'odbc_adapter/version'
|
@@ -22,9 +21,9 @@ Gem::Specification.new do |spec|
|
|
22
21
|
|
23
22
|
spec.add_dependency 'ruby-odbc', '~> 0.9'
|
24
23
|
|
25
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
26
|
-
spec.add_development_dependency '
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency '
|
29
|
-
spec.add_development_dependency '
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
25
|
+
spec.add_development_dependency 'minitest', '~> 5.10'
|
26
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
27
|
+
spec.add_development_dependency 'rubocop', '0.48.1'
|
28
|
+
spec.add_development_dependency 'simplecov', '~> 0.14'
|
30
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odbc_adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Localytics
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-odbc
|
@@ -30,70 +30,70 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
33
|
+
version: '1.14'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
40
|
+
version: '1.14'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '10
|
47
|
+
version: '5.10'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '10
|
54
|
+
version: '5.10'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '12.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '12.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.48.1
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.48.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
89
|
+
version: '0.14'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
96
|
+
version: '0.14'
|
97
97
|
description:
|
98
98
|
email:
|
99
99
|
- oss@localytics.com
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- ".gitignore"
|
105
105
|
- ".rubocop.yml"
|
106
106
|
- ".travis.yml"
|
107
|
+
- Dockerfile.dev
|
107
108
|
- Gemfile
|
108
109
|
- LICENSE
|
109
110
|
- README.md
|
@@ -111,6 +112,8 @@ files:
|
|
111
112
|
- bin/ci-setup
|
112
113
|
- bin/console
|
113
114
|
- bin/setup
|
115
|
+
- docker/docker-entrypoint.sh
|
116
|
+
- docker/test.sh
|
114
117
|
- lib/active_record/connection_adapters/odbc_adapter.rb
|
115
118
|
- lib/odbc_adapter.rb
|
116
119
|
- lib/odbc_adapter/adapters/mysql_odbc_adapter.rb
|
@@ -147,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
150
|
version: '0'
|
148
151
|
requirements: []
|
149
152
|
rubyforge_project:
|
150
|
-
rubygems_version: 2.
|
153
|
+
rubygems_version: 2.4.5
|
151
154
|
signing_key:
|
152
155
|
specification_version: 4
|
153
156
|
summary: An ActiveRecord ODBC adapter
|