Edited at

IfxPyでInformixに接続

PythonでInformixに繋ぐまともな方法はなかった。

あるとすれば以下の2つ。


  • PyODBCでODBC経由

  • JayDeBeApiでJDBC経由

遂にIfxPyがやってきた。


IfxPy


  • Python2/3 対応のネイティブドライバー

  • pip install IfxPy インストール可能

IfxPy - PyPi

IfxPy - Github

素晴らしい!

今まで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()のような関数が悪さをしている

を伝えておいた。

次の次あたりに治っているといいな。