From e0dce582154afb55bc8c923164c44200fc3c7a5d Mon Sep 17 00:00:00 2001 From: Kevin Deisz Date: Fri, 3 Feb 2017 13:50:47 -0500 Subject: [PATCH 1/2] Null adapter --- README.md | 6 ++- .../adapters/null_odbc_adapter.rb | 31 ++++++++++++ lib/odbc_adapter/registry.rb | 50 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 lib/odbc_adapter/adapters/null_odbc_adapter.rb create mode 100644 lib/odbc_adapter/registry.rb diff --git a/README.md b/README.md index 6390a403..bff38dfe 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,11 @@ [![Build Status](https://travis-ci.com/localytics/odbc_adapter.svg?token=kQUiABmGkzyHdJdMnCnv&branch=master)](https://travis-ci.com/localytics/odbc_adapter) -An ActiveRecord ODBC adapter. +An ActiveRecord ODBC adapter. Master branch is working off of edge Rails. 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. + +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. + +A lot of this work is based on [OpenLink's ActiveRecord adapter](http://odbc-rails.rubyforge.org/) which works for earlier versions of Rails. ## Installation diff --git a/lib/odbc_adapter/adapters/null_odbc_adapter.rb b/lib/odbc_adapter/adapters/null_odbc_adapter.rb new file mode 100644 index 00000000..1a179905 --- /dev/null +++ b/lib/odbc_adapter/adapters/null_odbc_adapter.rb @@ -0,0 +1,31 @@ +module ODBCAdapter + module Adapters + # A default adapter used for databases that are no explicitly listed in the + # registry. This allows for minimal support for DBMSs for which we don't + # have an explicit adapter. + class NullODBCAdapter < ActiveRecord::ConnectionAdapters::ODBCAdapter + class BindSubstitution < Arel::Visitors::ToSql + include Arel::Visitors::BindVisitor + end + + # Using a BindVisitor so that the SQL string gets substituted before it is + # sent to the DBMS (to attempt to get as much coverage as possible for + # DBMSs we don't support). + def arel_visitor + BindSubstitution.new(self) + end + + # Explicitly turning off prepared_statements in the null adapter because + # there isn't really a standard on which substitution character to use. + def prepared_statements + false + end + + # Turning off support for migrations because there is no information to + # go off of for what syntax the DBMS will expect. + def supports_migrations? + false + end + end + end +end diff --git a/lib/odbc_adapter/registry.rb b/lib/odbc_adapter/registry.rb new file mode 100644 index 00000000..1bb7264e --- /dev/null +++ b/lib/odbc_adapter/registry.rb @@ -0,0 +1,50 @@ +module ODBCAdapter + class Registry + attr_reader :dbs + + def initialize + @dbs = { + /my.*sql/i => :MySQL, + /postgres/i => :PostgreSQL + } + end + + def adapter_for(reported_name) + reported_name = reported_name.downcase.gsub(/\s/, '') + found = + dbs.detect do |pattern, adapter| + adapter if reported_name =~ pattern + end + + normalize_adapter(found && found.last || :Null) + end + + def register(pattern, superclass = Object, &block) + dbs[pattern] = Class.new(superclass, &block) + end + + private + + def normalize_adapter(adapter) + return adapter unless adapter.is_a?(Symbol) + require "odbc_adapter/adapters/#{adapter.downcase}_odbc_adapter" + Adapters.const_get(:"#{adapter}ODBCAdapter") + end + end + + class << self + def adapter_for(reported_name) + registry.adapter_for(reported_name) + end + + def register(pattern, superclass = Object, &block) + registry.register(pattern, superclass, &block) + end + + private + + def registry + @registry ||= Registry.new + end + end +end From c384ed8e4729502e791956fea7666664473c9185 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Wed, 31 Jan 2018 16:52:13 -0800 Subject: [PATCH 2/2] Backport support for Null to the DBMS class --- lib/odbc_adapter/dbms.rb | 3 +-- lib/odbc_adapter/registry.rb | 50 ------------------------------------ 2 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 lib/odbc_adapter/registry.rb diff --git a/lib/odbc_adapter/dbms.rb b/lib/odbc_adapter/dbms.rb index d5ede8c9..d59cd21a 100644 --- a/lib/odbc_adapter/dbms.rb +++ b/lib/odbc_adapter/dbms.rb @@ -42,8 +42,7 @@ def adapter adapter if reported =~ pattern end - raise ArgumentError, "ODBCAdapter: Unsupported database (#{reported})" if found.nil? - found.last + (found && found.last) || :Null end end end diff --git a/lib/odbc_adapter/registry.rb b/lib/odbc_adapter/registry.rb deleted file mode 100644 index 1bb7264e..00000000 --- a/lib/odbc_adapter/registry.rb +++ /dev/null @@ -1,50 +0,0 @@ -module ODBCAdapter - class Registry - attr_reader :dbs - - def initialize - @dbs = { - /my.*sql/i => :MySQL, - /postgres/i => :PostgreSQL - } - end - - def adapter_for(reported_name) - reported_name = reported_name.downcase.gsub(/\s/, '') - found = - dbs.detect do |pattern, adapter| - adapter if reported_name =~ pattern - end - - normalize_adapter(found && found.last || :Null) - end - - def register(pattern, superclass = Object, &block) - dbs[pattern] = Class.new(superclass, &block) - end - - private - - def normalize_adapter(adapter) - return adapter unless adapter.is_a?(Symbol) - require "odbc_adapter/adapters/#{adapter.downcase}_odbc_adapter" - Adapters.const_get(:"#{adapter}ODBCAdapter") - end - end - - class << self - def adapter_for(reported_name) - registry.adapter_for(reported_name) - end - - def register(pattern, superclass = Object, &block) - registry.register(pattern, superclass, &block) - end - - private - - def registry - @registry ||= Registry.new - end - end -end