Поставили задачу на работе, перевести приложения с PostgreSQL под СУБД Informix. Ничто не поделаешь... Взял доки, подключил инет и начал шаманить :) Что из этого вышло читаем в статье.

Задачи:

1. Установить Informix clientSDK в Ubuntu

2. Настроить clientSDK + unixODBC

3. Связать Qt4 и Informix через unixODBC

Что имеем, клиент:

Linux serge-noutebook 2.6.38-8-generic-pae #42-Ubuntu SMP Mon Apr 11 05:17:09 UTC 2011 i686 i686 i386 GNU/Linux

Сервак:

# uname -a

Linux rhel.local 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:43 EDT 2010 i686 i686 i386 GNU/Linux

# /etc/init.d/informix status

IBM Informix Dynamic Server Version 11.50.UC4DE -- On-Line -- Up 00:11:13 -- 745072 Kbytes

onconfig - дефолтен

sqlhosts:

#demo_on onipcshm on_hostname on_servername
#demo_se seipcpip se_hostname sqlexec
#bgd onsoctcp 192.168.10.242 port_alias
bgd onsoctcp 192.168.219.130 port_alias

Переменные окружения на сервере:

export INFORMIXDIR=/usr/informix/
export INFORMIXSERVER=bgd
export PATH=$INFORMIXDIR/bin:$PATH

export CLIENT_LOCALE=ru_RU.UTF8
export DB_LOCALE=ru_RU.UTF8
export SERVER_LOCALE=ru_RU.UTF8

Строка с номером порта в /etc/service :

port_alias 8201/tcp # informix

Итак начнемс :)

Ставим unixODBC

sudo apt-get install unixodbc*

Далее скачиваем для нужного дистрибутива clientsdk с сайта Informix client SDK. Но в связи с багнотостью регистрации, выложу файлик у себя на сервере(если IBM не понравится, думаю они сообщат:))(мне например на работе так и не удалось зарегаться на сайте IBM, в связи с "замечательном" фаерволом на моей работе). Для моего дистрибутива подходит clientsdk.3.70.UC2.LINUX.tar, что и качаем, можно и у меня.

Ставится клиент просто, распаковываем, запускаем installclientsdk. Я выбрал директорию установки /opt/IBM/informix/ и выбрал полную установку:

clientsdk_install_1

И так, после завершения установки, нужно задать некоторые переменные окружения. Я забил их в $HOME/.bashrc:

export ODBCINI=/etc/odbc.ini
export ODBCINIINST=/etc/odbcinst.ini
export INFORMIXDIR=/opt/IBM/informix
export SQLHOST=$INFORMIXDIR/etc/sqlhosts
export LD_LIBRARY_PATH=$INFORMIXDIR/lib:$INFORMIXDIR/lib/cli:$INFORMIXDIR/lib/esql
export DB_LOCALE=ru_RU.UTF8
export CLIENT_LOCALE=ru_RU.UTF8

Тут только одно замечание, переменные DB_LOCALE и CLIENT_LOCALE выставляете свои, в соответсвии с настойками сервера Informix.

Ecли пропустить переменную LD_LIBRARY_PATH, то будем получать в дальнейшем ошибки вида:

QODBC3: Unable to connect [unixODBC][Driver Manager]Can't open lib '/opt/IBM/informix/lib/cli/iclit09b.so' : file not found

Или например от iodbctest

$ iodbctest
iODBC Demonstration program
This program shows an interactive SQL processor
Driver Manager: 03.52.0607.1008

Enter ODBC connect string (? shows list): ?

DSN | Driver
------------------------------------------------------------------------------
bgd | IBM INFORMIX ODBC DRIVER

Enter ODBC connect string (? shows list): bgd
1: SQLDriverConnect = [iODBC][Driver Manager]libifgls.so: невозможно открыть разделяемый объектный файл: Нет такого файла или каталога (0) SQLSTATE=00000
2: SQLDriverConnect = [iODBC][Driver Manager]Specified driver could not be loaded (0) SQLSTATE=IM003

Смотрим ради интереса, с какими либами залинкована библиотечка /opt/IBM/informix/lib/cli/iclit09b.so, и видим, что ей что то не хватает :) Для этого и вводим LD_LIBRARY_PATH:

$ ldd /opt/IBM/informix/lib/cli/iclit09b.so
linux-gate.so.1 => (0xb77a6000)
libifgls.so => not found
libifglx.so => not found
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb75f9000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7498000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7472000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb746e000)
libcrypt.so.1 => /lib/i386-linux-gnu/libcrypt.so.1 (0xb743d000)
/lib/ld-linux.so.2 (0xb77a7000)

И так, с переменными окружения все(как мне кажется). Приступим теперь к настойке ODBC. В директории $INFORMIXDIR/etc/ есть два примерных файла с настройками для ODBC, это - odbc.ini и odbcinst.ini. Первый это список серверов, и настроек для подключения, второй это настройка самого драйвера для подключения к Infrmix. Можно просто скопировать их в /etc/ и потом поправить. Я привожу в пример свои файлы настроек:

odbc.ini

$ cat /etc/odbc.ini
[ODBC Data Sources]
bgd=IBM INFORMIX ODBC DRIVER

[bgd]
Driver=/opt/IBM/informix/lib/cli/iclit09b.so
Description=IBM INFORMIX ODBC DRIVER
Database=bkilo
LogonID=informix
pwd=informix
Servername=bgd
CLIENT_LOCALE=ru_RU.57372
DB_LOCALE=ru_RU.57372
ENABLESCROLLABLECURSORS=1

Хочется отметить переменную ENABLESCROLLABLECURSORS, говорят, что без нее QODBC работать не будет.

odbcinst.ini

$ cat /etc/odbcinst.ini

[ODBC Drivers]
IBM INFORMIX ODBC DRIVER=Installed
[IBM INFORMIX ODBC DRIVER]
Driver=/opt/IBM/informix/lib/cli/iclit09b.so
Setup=/opt/IBM/informix/lib/cli/iclis09b.so
APILevel=1
ConnectFunctions=YYY
DriverODBCVer=03.51
FileUsage=0
SQLLevel=1

Так же, необходимо прописать номер порта, который слушает сервер Informix, и обозвать его так же, как назвали его в /opt/IBM/informix/etc/sqlhosts. Строку добавляем в /etc/services

informix_sql 8201/tcp # Infromix SQL

Настройки unixODBC завершены. Проверяем как работают утилы isql и iodbctest:

$ isql bgd
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> quit

$ iodbctest "DSN=bgd;UID=informix;PWD=infM INFORMIX ODBC DRIVER};"
iODBC Demonstration program
This program shows an interactive SQL processor
Driver Manager: 03.52.0607.1008
Driver: 3.70.0000 3.70.U (iclis09b.so)

SQL>quit

Have a nice day.

 

Маленькое замечание. Если! если у вас сервер в ru_RU.UTF8 и клиент ru_RU.UTF8б необходимо скопировать след файлик - $INFORMIXDIR/gls/lc11/en_us/e01c.lco в $INFORMIXDIR/gls/lc11/ru_ru/e01c.lco как на клиентах, так и на сервере.

Как видим все работает.

Переходим к Qt. Версия Qt у меня:

$ qmake-qt4 --version
QMake version 2.01a
Using Qt version 4.7.2 in /usr/lib

Ставим пакет для поддержки ODBC:

sudo apt-get install libqt4-sql-odbc

Впринцыпе все. Но есть костыли, с которым я разбираюсь.

Код:

QSqlDatabase database = QSqlDatabase::addDatabase("QODBC");
database.setDatabaseName("DSN=bgd;UID=informix;PWD=informix;DRIVER={IBM INFORMIX ODBC DRIVER};");
database.setConnectOptions("SQL_ATTR_ODBC_VERSION=SQL_OV_ODBC3");
if(!database.open()){
QMessageBox::critical(this, "Ошибка", QString("%1\n%2\n%3\n(%4:%5)")
.arg(database.lastError().driverText())
.arg(database.lastError().databaseText())
.arg("Обратитесь к системному администратору.")
.arg(FILE)
.arg(__LINE__));
}

И получаю загадочную ошибку при открытии БД:

odbc_error

 

QODBC3: Unable to connect

[unixODBC][

Так что последний пункт повестки открыт :(

Добавил 16:44 18.05.2011

Итак салют найде. Второй день рыская по инету, нашел баг репорт: http://bugreports.qt.nokia.com/browse/QTBUG-14808

И теперь пишу салют.

Нам понадобятся исходники qt, или исходники драйвера ODBC для Qt. Сами исходники библиотеки скачать можно у тролей, у себя выложу только исходники QODBC поправленные мной.

1. Распаковываем исходники qt(я скачал qt-everywhere-opensource-src-4.7.3.tar.gz

2. Идем в папку qt-everywhere-opensource-src-4.7.3/src/plugins/sqldrivers/odbc/ и правим файл odbc.pro. Добавляем строчку DEFINES += Q_ODBC_VERSION_2

3. делаем qmake(qmake-qt4 "INCLUDEPATH+="куда_ставили/unixODBC-2.3.0/include/" "LIBS+=-L/usr/lib -lodbc")

4. Кидаем патч в qt-everywhere-opensource-src-4.7.3 и накладываем его patch -p1 < bug-14808.patch

5. make

6. sudo make install

Все :)

Пример кода для работы с ODBC + Informix

  QSqlDatabase database = QSqlDatabase::addDatabase("QODBC");
  database.setDatabaseName("DSN=bgd;DRIVER=IBM");
  if(!database.open()){
    QMessageBox::critical(this, "Ошибка", QString("%1\n%2\n%3\n(%4:%5)")
                          .arg(database.lastError().driverText())
                          .arg(database.lastError().databaseText())
                          .arg("Обратитесь к системному администратору.")
                          .arg(FILE)
                          .arg(__LINE__));
  }

Приложу так же уже пропатченный и отредактированный мной odbc driver для qt. Он включает в себя уже патч и готов к сборке. Распаковываем, даем команду

qmake-qt4 "INCLUDEPATH+="куда_ставили/unixODBC-2.3.0/include/" "LIBS+=-L/usr/lib -lodbc" и потом sudo cp libqsqlodbc.so* /usr/lib/qt4/plugins/sqldrivers/

И все :)

P.S. Я упустил один момент. Допустим у вас базы в UTF8, ну и допустим клиент тоже в UTF8... Все описанное выше работать не будет... Если не сделать следующие... :) Всего нада скопировать $INFORMIXDIR/gls/lc11/en_us/e01c.lco в папку $INFORMIXDIR/gls/lc11/ru_ru/