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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4debf1d258924d263e9f5979f9264048a046dad7
4
- data.tar.gz: 4211fdf1c9b1674d521319eca06ceb5f1060c643
3
+ metadata.gz: 89df3abd57cdeb10fd9d90428b53d3394a8dd14c
4
+ data.tar.gz: 30144892fafcb6eae63c2a96bed10cf7f9195839
5
5
  SHA512:
6
- metadata.gz: 246b9da217696c875c1df669064d7e7198d8b8505aaf70358125ec77fb90152ba93555b5d8ccbde4c15af85934aebd9277be6c00751d71e78f4a409516da8400
7
- data.tar.gz: 015bd47b7d7208c088ed6ecd6f1357e2a24e3c5d3513205bb0d56303396a1d7d868ab2691990782ee3d827033efa41997d553500580cc08a696b843bf997cb09
6
+ metadata.gz: afb573a1a3a59041ea84318b9d084a709c25016dd7c7e830941c90918a2d23fb28e8e003feadd167790dc5650a2defe2a57d9c60f69a565cc34179f3ce47e4c7
7
+ data.tar.gz: fefefa7812c4ed82f3c5b7b033f04fe91776c8a4039eddfddcdab31ad75e8be46ebf8436de63f40cf27aa86d9e95408546b1a40f33b2d82e5f04abcd2a8694d2
@@ -1,10 +1,13 @@
1
1
  AllCops:
2
2
  DisplayCopNames: true
3
3
  DisplayStyleGuide: true
4
- TargetRubyVersion: 2.0
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
- '%w': '[]'
32
- '%i': '[]'
34
+ default: '[]'
35
+ '%r': '{}'
@@ -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
@@ -3,4 +3,4 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'activerecord', '5.0.1'
6
- gem 'pry', '0.10.4'
6
+ gem 'pry', '~> 0.11.1'
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
@@ -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
- connection = ODBC.connect(config[:dsn], username, password)
44
- [connection, config.merge(username: username, password: password)]
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
- driver = ODBC::Driver.new
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 = config[:conn_str].split(';').map { |option| option.split('=', 2) }.to_h
60
+ driver.attrs = attrs
55
61
 
56
- connection = ODBC::Database.new.drvconnect(driver)
57
- [connection, config.merge(driver: driver)]
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 = 23_505
73
- ERR_QUERY_TIMED_OUT = 57_014
74
- ERR_QUERY_TIMED_OUT_MESSAGE = /Query has timed out/
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
- ODBC.connect(@config[:dsn], @config[:username], @config[:password])
122
+ odbc_module.connect(@config[:dsn], @config[:username], @config[:password])
113
123
  else
114
- ODBC::Database.new.drvconnect(@config[:driver])
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 [:text, :binary].include?(abstract)
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
- def initialize(connection)
19
- @values = Hash[FIELDS.map { |field| [field, connection.get_info(ODBC.const_get(field))] }]
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
@@ -1,4 +1,6 @@
1
1
  module ODBCAdapter
2
2
  class QueryTimeoutError < ActiveRecord::StatementInvalid
3
3
  end
4
+ class ConnectionFailedError < ActiveRecord::StatementInvalid
5
+ end
4
6
  end
@@ -1,3 +1,3 @@
1
1
  module ODBCAdapter
2
- VERSION = '5.0.3'.freeze
2
+ VERSION = '5.0.5'.freeze
3
3
  end
@@ -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.13'
26
- spec.add_development_dependency 'rake', '~> 10.0'
27
- spec.add_development_dependency 'minitest', '~> 5.0'
28
- spec.add_development_dependency 'simplecov', '~> 0.12'
29
- spec.add_development_dependency 'rubocop', '~> 0.47'
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.3
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: 2017-03-07 00:00:00.000000000 Z
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.13'
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.13'
40
+ version: '1.14'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
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.0'
54
+ version: '5.10'
55
55
  - !ruby/object:Gem::Dependency
56
- name: minitest
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '5.0'
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: '5.0'
68
+ version: '12.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: simplecov
70
+ name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: '0.12'
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: '0.12'
82
+ version: 0.48.1
83
83
  - !ruby/object:Gem::Dependency
84
- name: rubocop
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.47'
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.47'
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.6.8
153
+ rubygems_version: 2.4.5
151
154
  signing_key:
152
155
  specification_version: 4
153
156
  summary: An ActiveRecord ODBC adapter