PythonでInformixに繋ぐまともな方法はなかった。
あるとすれば以下の2つ。
- PyODBCでODBC経由
- JayDeBeApiでJDBC経由
遂にIfxPyがやってきた。
##IfxPy
- Python2/3 対応のネイティブドライバー
- pip install IfxPy インストール可能
素晴らしい!
今までJayDeBeApiでInformixに繋いでいた。
IfxPyだけで繋げられるようになると非常に楽になる。
早速試してみることにした。
環境
Client
- vagrant box generic/debian10
- Informix Client SDK 4.50FC1
- CLIENT_LOCALE=ja_jp.utf8
Locale
$ localectl
System Locale: LANG=ja_JP.UTF-8
LANGUAGE=ja_JP:ja
VC Keymap: n/a
X11 Layout: us
X11 Model: pc105
Server
- CentOS7
- Informix Dynamic Server 12.10FCWE12
- DB_LOCALE=ja_jp.sjis-s
手順
# make csdk folder
$ mkdir csdk
# extract
$ tar -xvf clientsdk.4.10.FC9DE.LINUX.tar -C csdk
$ cd csdk
# Install Library for installclientcsdk
$ sudo apt -y install libaio1 bc libncurses5 ncurses-bin libpam0g
$ sudo apt -y install libncurses5-dev libelf1
# Install
$ sudo ./installclientcsdk -i console
# SET Environment Variables
# export INFORMIXDIR=/opt/IBM/informix # CSDK 4.10
export INFORMIXDIR=/opt/IBM/Informix_Client-SDK #CSDK 4.50
export LD_LIBRARY_PATH=${INFORMIXDIR}/lib:${INFORMIXDIR}/lib/esql:${INFORMIXDIR}/lib/cli
# Make sqlhosts
$ sudo cp /opt/IBM/Informix_Client-SDK/etc/sqlhosts.std /opt/IBM/Informix_Client-SDK/etc/sqlhosts
$ vi /opt/IBM/Informix_Client-SDK/etc/sqlhosts
# ...etc....
servername onsoctcp serverip 21435
# SET DB_LOCALE
$ export DB_LOCALE=ja_jp.sjis-s
# SET CLIENT_LOCALE
$ export DB_LOCALE=ja_jp.utf8
# pip install
$ sudo apt install python3-pip
# Install IfxPy
$ pip3 install IfxPy --user
# make python file
$ vi ifxcnnt.py
# Execute Python3
$ python3 ifxcnnt.py
Traceback (most recent call last):
File "ifxcnnt.py", line 6, in <module>
conn=IfxPy.connect(ConStr,"","")
Exception: [Informix][Informix ODBC Driver][Informix]Error opening required code-set conversion
あれ?
繋がらないぞ。
GitHubにIssue立てた。
Don't deal Japanese
jsagrera氏によるとConnectionStringにDB_LOCALEとCLIENT_LOCALEを書き足すと繋がるそうだ。
下記のように書く。
code
#! /usr/bin/env python3
import IfxPyDbi as dbapi2
ConnectionString="SERVER=servername;DATABASE=database;HOST=IP;SERVICE=21435;UID=username;PWD=password;PROTOCOL=onsoctcp;CLIENT_LOCALE=ja_jp.utf8;DB_LOCALE=ja_jp.sjis-s"
conn=dbapi2.connect(ConnectionString,"","")
cur=conn.cursor()
cur.execute("select 得意先名 from 得意先m where 得意先cd=1")
rows=cur.fetchall()
for i,row in enumerate(rows):
print("Row",i,"value=",row)
cur.close()
conn.close()
print("Done")
動くかな?
result
$ python3 ifxfetchall.py
Row 0 value= ('株式会社 ',)
Done
よし!動いた。
日本語カラム対策
日本語のカラム名を指定すると動かない関数がある。
僕が探した中では下記の4つ。
- ifxPy.fetch_both
- ifxPy.fetch_assoc
- IfxPy.field_name
- IfxPy.result
SQLのASを使ってカラム名をASCIIな名前に変更する。
それで回避できる。
ifxPy.fetch_bothを例にしてみる。
ifxPy.fetch_both
# Connection ConnectionStringなど省略
sql="SELECT 得意先cd as customer_cd, 得意先名 as customer_name from 得意先m where 得意先cd=1 or 得意先cd=2"
stmt=IfxPy.exec_immediate(conn,sql)
dic=IfxPy.fetch_both(stmt)
while dic != False:
print(dic["customer_cd"])
print(dic["customer_name"])
dic=IfxPy.fetch_both(stmt)
IfxPy.free_result(stmt)
IfxPy.free_stmt(stmt)
IfxPy.close(conn)
さあ動くかな?
result
$ python3 ifxfetchboth.py
2
株式会社 東京支店
1
株式会社
よし動いた!
終わりに
僕が建てたGitHub Issueでは
- 4つの関数が日本語カラムを扱えない。
- それらのCのコードのPyUnicode_AsASCIIString()のような関数が悪さをしている
を伝えておいた。
次の次あたりに治っているといいな。