Skip to content

Commit

Permalink
Merge pull request #2 from jbender/travis
Browse files Browse the repository at this point in the history
Re-enable expanded test suite
  • Loading branch information
nickelser authored Feb 20, 2019
2 parents 8b6a2c3 + 294f56b commit 34cd3e8
Show file tree
Hide file tree
Showing 18 changed files with 274 additions and 90 deletions.
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
AllCops:
DisplayCopNames: true
DisplayStyleGuide: true
TargetRubyVersion: 2.1
TargetRubyVersion: 2.2
Exclude:
- 'vendor/**/*'

Expand Down
66 changes: 40 additions & 26 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
sudo: required
language: ruby
cache: bundler
matrix:
include:
- rvm: 2.3.1
env:
- DB=mysql
- CONN_STR='DRIVER=MySQL;SERVER=localhost;DATABASE=odbc_test;USER=root;PASSWORD=;'
addons:
mysql: "5.5"
apt:
packages:
- unixodbc
- unixodbc-dev
- libmyodbc
- mysql-client
- rvm: 2.3.1
env:
- DB=postgresql
- CONN_STR='DRIVER={PostgreSQL ANSI};SERVER=localhost;PORT=5432;DATABASE=odbc_test;UID=postgres;'
addons:
postgresql: "9.1"
apt:
packages:
- unixodbc
- unixodbc-dev
- odbc-postgresql
before_script: bin/ci-setup

services:
- postgresql
- mysql

addons:
apt:
packages:
- unixodbc
- unixodbc-dev
# MySQL
- libmyodbc
- mysql-client-5.6
# Postgres
- odbc-postgresql

rvm:
- 2.3
- 2.4
- 2.5

env:
- DB=mysql CONN_STR='DRIVER=MySQL;SERVER=localhost;DATABASE=odbc_test;USER=root;PASSWORD=;'
- DB=postgresql CONN_STR='DRIVER={PostgreSQL ANSI};SERVER=localhost;PORT=5432;DATABASE=odbc_test;UID=postgres;'

before_install:
- gem update --system

gemfile:
- gemfiles/active_record_5_0.gemfile
- gemfiles/active_record_5_1.gemfile
- gemfiles/active_record_5_2.gemfile

before_script:
- sh -c "if [ '$DB' = 'mysql' ]; then sudo odbcinst -i -d -f /usr/share/libmyodbc/odbcinst.ini; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'DROP DATABASE IF EXISTS odbc_test; CREATE DATABASE IF NOT EXISTS odbc_test;' -uroot; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'GRANT ALL PRIVILEGES ON *.* TO "root"@"localhost";' -uroot; fi"

- sh -c "if [ '$DB' = 'postgresql' ]; then sudo odbcinst -i -d -f /usr/share/psqlodbc/odbcinst.ini.template; fi"
- sh -c "if [ '$DB' = 'postgresql' ]; then psql -c 'CREATE DATABASE odbc_test;' -U postgres; fi"
3 changes: 0 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
source 'https://rubygems.org'

gemspec

gem 'activerecord', '5.0.1'
gem 'pry', '~> 0.11.1'
66 changes: 52 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
# ODBCAdapter
# ODBCAdapter [![License][license-badge]][license-link]

[![Build Status](https://travis-ci.org/localytics/odbc_adapter.svg?branch=master)](https://travis-ci.org/localytics/odbc_adapter)
[![Gem](https://img.shields.io/gem/v/odbc_adapter.svg)](https://rubygems.org/gems/odbc_adapter)
| ActiveRecord | Gem Version | Branch | Status |
|--------------|-------------|--------|--------|
| `5.x` | `~> '5.0'` | [`master`][5.x-branch] | [![Build Status][5.x-build-badge]][build-link] |
| `4.x` | `~> '4.0'` | [`4.2.x`][4.x-branch] | [![Build Status][4.x-build-badge]][build-link] |

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.
## Supported Databases

This adapter will work for basic queries for most DBMSs out of the box, without support for migrations. Full support is built-in for MySQL 5 and PostgreSQL 9 databases. You can register your own adapter to get more support for your DBMS using the `ODBCAdapter.register` function.
- PostgreSQL 9
- MySQL 5
- Snowflake

A lot of this work is based on [OpenLink's ActiveRecord adapter](http://odbc-rails.rubyforge.org/) which works for earlier versions of Rails.
You can also register your own adapter to get more support for your DBMS
`ODBCAdapter.register`.

## Installation

Ensure you have the ODBC driver installed on your machine. You will also need the driver for whichever database to which you want ODBC to connect.
Ensure you have the ODBC driver installed on your machine. You will also need
the driver for whichever database to which you want ODBC to connect.

Add this line to your application's Gemfile:

Expand All @@ -29,32 +35,64 @@ Or install it yourself as:

## Usage

Configure your `database.yml` by either using the `dsn` option to point to a DSN that corresponds to a valid entry in your `~/.odbc.ini` file:
Configure your `database.yml` by either using the `dsn` option to point to a DSN
that corresponds to a valid entry in your `~/.odbc.ini` file:

```
```yml
development:
adapter: odbc
dsn: MyDatabaseDSN
```
or by using the `conn_str` option and specifying the entire connection string:

```
```yml
development:
adapter: odbc
conn_str: "DRIVER={PostgreSQL ANSI};SERVER=localhost;PORT=5432;DATABASE=my_database;UID=postgres;"
```

ActiveRecord models that use this connection will now be connecting to the configured database using the ODBC driver.
ActiveRecord models that use this connection will now be connecting to the
configured database using the ODBC driver.

### Extending

Configure your own adapter by registering it in your application's bootstrap
process. For example, you could add the following to a Rails application via
`config/initializers/custom_database_adapter.rb`

```ruby
ODBCAdapter.register(/custom/, ActiveRecord::ConnectionAdapters::ODBCAdapter) do
# Overrides
end
```

```yml
development:
adapter: odbc
dsn: CustomDB
```

## Testing

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.

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/localytics/odbc_adapter.
Bug reports and pull requests are welcome on [GitHub][github-repo].

## Prior Work

## License
A lot of this work is based on [OpenLink's ActiveRecord adapter][openlink-activerecord-adapter] which works for earlier versions of Rails. 5.0.x compatability work was completed by the [Localytics][localytics-github] team.

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
[4.x-branch]: https://github.com/localytics/odbc_adapter/tree/v4.2.x
[4.x-build-badge]: https://travis-ci.org/localytics/odbc_adapter.svg?branch=4.2.x
[5.x-branch]: https://github.com/localytics/odbc_adapter/tree/master
[5.x-build-badge]: https://travis-ci.org/localytics/odbc_adapter.svg?branch=master
[build-link]: https://travis-ci.org/localytics/odbc_adapter/branches
[github-repo]: https://github.com/localytics/odbc_adapter
[license-badge]: https://img.shields.io/github/license/localytics/odbc_adapter.svg
[license-link]: https://github.com/localytics/odbc_adapter/blob/master/LICENSE
[localytics-github]: https://github.com/localytics
[openlink-activerecord-adapter]: https://github.com/dosire/activerecord-odbc-adapter
[supported-versions-badge]: https://img.shields.io/badge/active__record-4.x--5.x-green.svg
28 changes: 19 additions & 9 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
require 'bundler/gem_tasks'
require 'rake/testtask'
require 'rubocop/rake_task'

Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList['test/**/*_test.rb']
task default: %i[rubocop test]

desc 'Run rubocop'
task :rubocop do
require 'rubocop/rake_task'

RuboCop::RakeTask.new do |task|
task.patterns = ['lib/**/*.rb']
task.formatters = ['simple']
end
end

RuboCop::RakeTask.new(:rubocop)
Rake::Task[:test].prerequisites << :rubocop
desc 'Run tests'
task :test do
require 'rake/testtask'

task default: :test
Rake::TestTask.new do |task|
task.libs << 'test'
task.libs << 'lib'
task.test_files = FileList['test/**/*_test.rb']
end
end
13 changes: 0 additions & 13 deletions bin/ci-setup

This file was deleted.

5 changes: 5 additions & 0 deletions gemfiles/active_record_5_0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'

gemspec(path: '..')

gem 'activerecord', '~> 5.0.1'
5 changes: 5 additions & 0 deletions gemfiles/active_record_5_1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'

gemspec(path: '..')

gem 'activerecord', '~> 5.1.0'
5 changes: 5 additions & 0 deletions gemfiles/active_record_5_2.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'

gemspec(path: '..')

gem 'activerecord', '~> 5.2.0'
1 change: 1 addition & 0 deletions lib/active_record/connection_adapters/odbc_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def disconnect!
def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil, native_type = nil)
::ODBCAdapter::Column.new(name, default, sql_type_metadata, null, table_name, default_function, collation, native_type)
end
# rubocop:enable Metrics/ParameterLists

protected

Expand Down
2 changes: 1 addition & 1 deletion lib/odbc_adapter/adapters/mysql_odbc_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def options_include_default?(options)

protected

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
def insert_sql(sql, name = nil, pri_key = nil, id_value = nil, sequence_name = nil)
super
id_value || last_inserted_id(nil)
end
Expand Down
37 changes: 22 additions & 15 deletions lib/odbc_adapter/adapters/postgresql_odbc_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ def arel_visitor
Arel::Visitors::PostgreSQL.new(self)
end

# Explicitly disable prepared statements for now, as it's always erroring
# out with:
# ODBC::Error: INTERN (0) [RubyODBC]Too much parameters
def prepared_statements
false
end

# Filter for ODBCAdapter#tables
# Omits table from #tables if table_filter returns true
def table_filtered?(schema_name, table_type)
Expand All @@ -29,19 +36,19 @@ def truncate(table_name, name = nil)

# Returns the sequence name for a table's primary key or some other
# specified key.
def default_sequence_name(table_name, pk = nil)
serial_sequence(table_name, pk || 'id').split('.').last
def default_sequence_name(table_name, pri_key = nil)
serial_sequence(table_name, pri_key || 'id').split('.').last
rescue ActiveRecord::StatementInvalid
"#{table_name}_#{pk || 'id'}_seq"
"#{table_name}_#{pri_key || 'id'}_seq"
end

def sql_for_insert(sql, pk, _id_value, _sequence_name, binds)
unless pk
def sql_for_insert(sql, pri_key, _id_value, _sequence_name, binds)
unless pri_key
table_ref = extract_table_ref_from_insert_sql(sql)
pk = primary_key(table_ref) if table_ref
pri_key = primary_key(table_ref) if table_ref
end

sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
sql = "#{sql} RETURNING #{quote_column_name(pri_key)}" if pri_key
[sql, binds]
end

Expand All @@ -50,7 +57,7 @@ def type_cast(value, column)

case value
when String
return super unless 'bytea' == column.native_type
return super unless column.native_type == 'bytea'
{ value: value, format: 1 }
else
super
Expand Down Expand Up @@ -158,14 +165,14 @@ def distinct(columns, orders)
protected

# Executes an INSERT query and returns the new record's ID
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
unless pk
def insert_sql(sql, name = nil, pri_key = nil, id_value = nil, sequence_name = nil)
unless pri_key
table_ref = extract_table_ref_from_insert_sql(sql)
pk = primary_key(table_ref) if table_ref
pri_key = primary_key(table_ref) if table_ref
end

if pk
select_value("#{sql} RETURNING #{quote_column_name(pk)}")
if pri_key
select_value("#{sql} RETURNING #{quote_column_name(pri_key)}")
else
super
end
Expand All @@ -180,9 +187,9 @@ def last_insert_id(sequence_name)
private

def serial_sequence(table, column)
result = exec_query(<<-eosql, 'SCHEMA')
result = exec_query(<<-EOSQL, 'SCHEMA')
SELECT pg_get_serial_sequence('#{table}', '#{column}')
eosql
EOSQL
result.rows.first.first
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/odbc_adapter/column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ def initialize(name, default, sql_type_metadata = nil, null = true, table_name =
super(name, default, sql_type_metadata, null, table_name, default_function, collation)
@native_type = native_type
end
# rubocop:enable Metrics/ParameterLists
end
end
14 changes: 7 additions & 7 deletions odbc_adapter.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# coding: utf-8

lib = File.expand_path('../lib', __FILE__)
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'odbc_adapter/version'

Expand All @@ -21,11 +19,13 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']

spec.add_dependency 'activerecord', '~> 5.0'
spec.add_dependency 'ruby-odbc', '~> 0.9'

spec.add_development_dependency 'bundler', '~> 1.14'
spec.add_development_dependency 'minitest', '~> 5.10'
spec.add_development_dependency 'rake', '~> 12.0'
spec.add_development_dependency 'rubocop', '~> 0.48'
spec.add_development_dependency 'bundler', '>= 1.14'
spec.add_development_dependency 'minitest', '~> 5.10'
spec.add_development_dependency 'pry', '~> 0.11'
spec.add_development_dependency 'rake', '~> 12.0'
spec.add_development_dependency 'rubocop', '<= 0.58'
spec.add_development_dependency 'simplecov', '~> 0.14'
end
Loading

0 comments on commit 34cd3e8

Please sign in to comment.