Pages

2012年9月5日水曜日

RubyでDB2/AS400に接続

今はAS400とは言わず、”System i” と呼ぶのだそうです。 職場でAS400上のDB2のデータを加工する簡単なバッチ処理プログラムを作成する必要があったので、rubyで作成してみることにしました。

この記事は、RubyでDB2にODBC接続を行う方法についての覚書です。DB2との接続について調査し、いくつか試しましたが、

  • ibm_db と言うデータベースドライバがgemで配布されているが、SQL CLI (call level interface)が必要
  • AS400クライアントパッケージ Client Accessで、ODBCドライバーを提供している
  • 意外とruby + windows + ODBCの記事が少ない
  • gemで配布されているruby-ODBCも、odbcドライバをコンパイルする必要がある(コンパイラ必要)

と言う状態。様は直接DB2に接続するドライバの入手は意外と大変で、ODBC接続が応用が利きそうだが、バイナリのODBCを入手する必要があります。 結局、採用した構成は、以下の図の通り。

ruby DBI (+ DBD::ODBC) -- Client Access ODBC Driver -- DB2/AS400

  DBI : Database Interface 汎用データベースアクセス クラス。SQLをパースし、DBDに渡す。
  DBD : DBIの下位層で各データベースとの接続を行う。DB毎に用意される。

今回使用したWindows PC環境は、以下の通り。

  • OS: WindowsXP
  • Ruby: Active Script Ruby (ruby version 1.8.7 rubygems も同梱されたパッケージ)
  • IBM AS400接続クライアント Client Access インストール済み

ODBCデータソースの設定

Windowsのコントロールパネル内の”ODBCデータソース”(だったかな)で設定します。ポイントだけ記載。

  1. システムDSN に追加
  2. client access odbc driver を使用
  3. serverタグの"SQLデフォルトライブラリ"に、データベースオブジェクトが格納されているライブラリを指定

Ruby DBIモジュールとODBCのDBD(DataBaseDriver)をインストール

DBIは、gem から

gem install dbi
gem install dbd-odbc

ODBCドライバのインストールは、以下を参考にした。 SequelでSQL ServerにODBC接続する

  1. バイナリのDBD::ODBCライブラリを入手。ODBC Binding for Ruby
  2. i386-msvcrt-ruby-odbc.zip を入手し解凍し、所定の位置に配布

入手したsoファイル(odbc.so, odbc_utf8.so)を置いたのは、私の場合 "C:¥ruby¥lib¥ruby¥1.8¥i386-mswin32" (注: 私は ActiveScriptRuby を C:¥rubyにインストールし、パスを通しているので、この位置)


接続テストのサンプルプログラム

以下のサイトにサンプルコードが記載されていたので、一部追加して、転記します。

Ruby DB2 ODBC - how to access a DB2 database on an As/400 or iSeries

require 'odbc'

require 'rubygems' # baker add
require 'dbi'

dbh = DBI.connect('DBI:ODBC:MY_AS400', 'MY_USER', 'MY_PASS')
sth = dbh.prepare('select count(*) from my_table')
sth.execute

# Print out each row
while row=sth.fetch do
  p row
end

sth.finish
dbh.disconnect

実際に irbで試してみる

実際にirbを使って、接続テストをしてみた。

C:\Documents and Settings\baker>irb
irb(main):001:0> require "odbc"
=> true
irb(main):002:0> require "rubygems"
=> true
irb(main):003:0> require "dbi"
=> true
irb(main):004:0> db = DBI.connect('DBI:ODBC:データソース名','ユーザ','パスワード')
=> #<DBI::DatabaseHandle:0x3393f0c @trace_output=nil, @driver_name="odbc", @trace_mode=nil, @convert_types=true, @handle
=#<DBI::DBD::ODBC::Database:0x3393e1c @handle=#<ODBC::Database:0x3393e58>, @attr={}>>

irb(main):005:0> st = db.prepare('select count(*) from テーブル名')
=> #<DBI::StatementHandle:0x338f9e8 @row=nil, @prepared=true, @coltypes=nil, @trace_output=nil, @fetchable=false, @raise
_error=nil, @cols=nil, @trace_mode=nil, @dbh=#<DBI::DatabaseHandle:0x3393f0c @last_statement="select count(*) from G2DNF
", @trace_output=nil, @driver_name="odbc", @trace_mode=nil, @convert_types=true, @handle=#<DBI::DBD::ODBC::Database:0x33
93e1c @handle=#<ODBC::Database:0x3393e58>, @attr={}>>, @executed=false, @convert_types=true, @handle=#<DBI::DBD::ODBC::S
tatement:0x338f920 @arr=[], @statement="select count(*) from xxxxxx", @params=[], @handle=#<ODBC::Statement:0x338f984>>>

irb(main):008:0> st.execute
=> nil

irb(main):009:0> st.fetch
=> [234402]

irb(main):010:0> st.finish
=> nil

irb(main):011:0> db.disconnect
=> nil

st.finish と db.disconnectは、効いてないっぽい。(儀式?)

0 件のコメント:

コメントを投稿