LoginSignup
1
1

More than 3 years have passed since last update.

IfxPyでInformixに接続

Last updated at Posted at 2019-09-27

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

を伝えておいた。
次の次あたりに治っているといいな。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1