Dans cet article on va voir comment on peut accéder a Sybase en utilisant UnixODBC a partir d’un client distant (32 bits). Deux possibilités sont offertes soit :
1. Récupérer une ancienne version de Sybase 32 bits (la 15.5 par exemple) et installer les libs coté client et particulièrement (ASE ODBC Driver), on a déjà fait ça dans un précédent article.
Une fois le client 32 bits installé, on configure les fichiers /etc/odbc.ini et /etc/odbcinst.ini comme suit :
toc@tocNewServer:~$ cat /etc/odbc.ini [SybasePubs2] Description = Sybase ODBC for pubs2 database Driver = /opt/sybase/DataAccess/ODBC/lib/libsybdrvodb.so Server = 192.168.1.95 Port = 5000 Database = pubs2 Trace = Yes TraceFile = /tmp/isql.log ForceTrace = Yes toc@tocNewServer:~$ cat /etc/odbcinst.ini [ODBC] Trace = yes TraceFile = /tmp/odbc.log
Ici on configure l’accès a la base pubs2 en utilisant le driver natif offert par Sybase, il s’agit de la librairie : /opt/sybase/DataAccess/ODBC/lib/libsybdrvodb.so. On peut ensuite tester tout ça avec (et exécuter une simple requête pour récupérer la version des composants installés coté serveur):
toc@tocNewServer:~$ isql -v SybasePubs2 tarek 123456 +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> sp_version +------------------+--------------------------------------------------------------------------------------------------------------------+---------+ | Script | Version | Status | +------------------+--------------------------------------------------------------------------------------------------------------------+---------+ | ODBC MDA Scripts | 15.7.0.403.1011/Fri Jul 06 UTC 00:41:49 2012 | Complete| | OLEDB MDA Scripts| 15.7.0.403.1011/Fri Jul 06 UTC 00:16:26 2012 | Complete| | installcommit | 15.7.0/EBF 20373 SMP ESD#02 /P/x86_64/Enterprise Linux/ase157esd2/3109/64-bit/OPT/Sat Jul 7 01:11:56 2012 | Complete| | installjdbc | jConnect (TM) for JDBC(TM)/7.07 ESD #4 (Build 26793)/P/EBF20302/JDK 1.6.0/jdbcmain/OPT/Thu Jul 5 22:08:44 PDT 2012| Complete| | installjsdb | 15.7.0/EBF 20373 SMP ESD#02 /P/x86_64/Enterprise Linux/ase157esd2/3109/64-bit/OPT/Sat Jul 7 01:11:56 2012 | Complete| | installmaster | 15.7.0/EBF 20373 SMP ESD#02 /P/x86_64/Enterprise Linux/ase157esd2/3109/64-bit/OPT/Sat Jul 7 01:11:56 2012 | Complete| | installmodel | 15.7.0/EBF 20373 SMP ESD#02 /P/x86_64/Enterprise Linux/ase157esd2/3109/64-bit/OPT/Sat Jul 7 01:11:56 2012 | Complete| | montables | 15.7.0/20373/P/x86_64/Enterprise Linux/ase157esd2/3109/64-bit/OPT/Sat Jul 07 00:57:46 2012 | Complete| +------------------+--------------------------------------------------------------------------------------------------------------------+---------+ SQLRowCount returns 95 8 rows fetched
Si vous avez une erreur du genre :
toc@tocNewServer:~$ isql -v SybasePubs2 tarek 123456 [01000][unixODBC][Driver Manager]Can't open lib '/opt/sybase/DataAccess/ODBC/lib/libsybdrvodb.so' : file not found [ISQL]ERROR: Could not SQLConnect
Faut modifier la valeur de LD_LIBRARY_PATH :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/sybase/DataAccess/ODBC/lib
Notez le grand avantage de passer par ce driver est : le fait que vous pouvez faire des requêtes en utilisant les « Stored Procedures » offertes par Sybase (par exemple sp_help, sp_sendmsg, sp_….)
2. Utilisez le projet libre FreeTDS qui implémente les protocoles d’accès a Sybase. Vous pouvez l’installer soit en récupérant les source avec :
# wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-stable.tgz # tar zfvx freetds-stable.tgz # cd freetds-* # ./configure --prefix=/usr/local/freetds --with-tdsver=8.0 --with-unixodbc=/usr/local/unixODBC # make # make install
Ou en utilisant apt (sous Ubuntu par example) :
# apt-get install freetds-common freetds-dev freetds-bin
Une fois qu’on a installé FreeTDS, on configure /etc/odbc.ini et /etc/odbcinst.ini, dans mon cas ça ressemble a ceci :
toc@tocNewServer:~$ cat /etc/odbc.ini [Sybase] Description = Sybase ODBC Driver = /usr/local/lib/libtdsodbc.so Server = 192.168.1.95 Port = 5000 toc@tocNewServer:~$ cat /etc/odbcinst.ini [ODBC] Trace = yes TraceFile = /tmp/odbc.log
Pareil, vous testez avec quelque chose du genre :
toc@tocNewServer:~$ isql -v Sybase tarek 123456 +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> select getdate() +------------------------+ | | +------------------------+ | 2013-06-24 22:42:50.487| +------------------------+ SQLRowCount returns 1 1 rows fetched
Une fois qu’on a configuré l’ODBC, on peux alors écrire un fichier C, hello-sybase-odbc.c :
/* * hello-sybase-odbc.c : ce programme demontre * une simple utilisation d'UnixODBC avec Sybase */ #include #include #include #include #define BUFFER_LEN 1024 #define OK 0 #define KO -1 #define TIMEOUT 5 /* Le timeout est fixe a 5 seconds */ #define REC_NUMBER 1 /* Pour la fonction SQLGetDiagRec */ #define SQLSTATE_LEN 7 #define DB_NAME_LEN 128 #define DB_VERSION_LEN 32 int odbc_connection(char *datasource, char *user, char *pwd) { long status; SQLCHAR state[SQLSTATE_LEN]; /* Pour SQLSTATE code qui designe une erreur ou un warning */ SQLINTEGER odbc_error; SQLSMALLINT error_text_len; SQLCHAR error_text[BUFFER_LEN]; SQLCHAR db_name[DB_NAME_LEN]; /* Nom de la base de donnees */ SQLCHAR db_version[DB_VERSION_LEN]; /* Version de la base de donnes */ SQLHENV environment_handle; /* Pour mettre en place notre environnement */ SQLHDBC connection_handle; /* Pour la connexion a la source de donnees */ SQLHSTMT statment_handle; /* Pour notre requete */ char result_buffer[1024]; /* Pour chaque ligne du resultat */ SQLRETURN ret; SQLSMALLINT columns; /* Nombre de colonnes dans le resultat */ int i; /* Etape 1. allocation de la memoire pour mettre en place notre environnement ODBC */ status = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &environment_handle); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLAllocHandle: SQL_HANDLE_ENV Failed\n"); return KO; } /* Tous les recents driver ODBC supporte la version 3 d'ODBC */ status = SQLSetEnvAttr(environment_handle, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, SQL_IS_INTEGER); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLSetEnvAttr Failed\n"); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return KO; } /* Etape 2. allocation de la memoire pour le handle de la connexion */ status = SQLAllocHandle(SQL_HANDLE_DBC, environment_handle, &connection_handle); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLAllocHandle: SQL_HANDLE_DBC Failed\n"); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return KO ; } /* Mise en place d'un timeout : temps d'attente d'une connexion */ SQLSetConnectAttr(connection_handle, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) TIMEOUT, 0); /* Etape 3. connexion a la source de donnees "datasource" */ /* On peut aussi utiliser la fonction SQLDriverConnect qui prend plus de parametres */ status = SQLConnect(connection_handle, (SQLCHAR *) datasource, SQL_NTS, (SQLCHAR *) user, SQL_NTS, (SQLCHAR *) pwd, SQL_NTS); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLConnect failed\n"); SQLGetDiagRec(SQL_HANDLE_DBC, connection_handle, REC_NUMBER, state, &odbc_error, error_text, BUFFER_LEN, &error_text_len); fprintf(stderr, "%s (error number : %d)\n", error_text, (int)odbc_error); SQLFreeHandle(SQL_HANDLE_DBC, connection_handle); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return KO; } fprintf(stdout, "Connection to DataSource %s succeeded\n", datasource); /* Le nom et la version de la base de donnees */ SQLGetInfo(connection_handle, SQL_DBMS_NAME, (SQLPOINTER)db_name, sizeof(db_name), NULL); SQLGetInfo(connection_handle, SQL_DBMS_VER, (SQLPOINTER)db_version, sizeof(db_version), NULL); fprintf(stdout, "Database name : %s\n", db_name); fprintf(stdout, "Database version : %s\n", db_version); /* Etape 3. allocation de la memoire pour la requete */ status = SQLAllocHandle(SQL_HANDLE_STMT, connection_handle, &statment_handle); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLAllocHandle: SQL_HANDLE_STMT Failed\n"); /* On se deconnecte avant de quitter */ status = SQLDisconnect(connection_handle); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLDisconnect failed\n"); SQLGetDiagRec(SQL_HANDLE_DBC, connection_handle, REC_NUMBER, state, &odbc_error, error_text, BUFFER_LEN, &error_text_len); fprintf(stderr, "%s (error number : %d)\n", error_text, (int)odbc_error); } SQLFreeHandle(SQL_HANDLE_DBC, connection_handle); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return KO; } /* Etape 4. Envoyer une requete via la procedure sp_clearstats, qui affiche les stats. * CECI NE FONCTIONNERA PAS SI VOTRE DRIVER ODBC EST FREETDS! */ status = SQLExecDirect(statment_handle, (SQLCHAR *)"sp_clearstats", SQL_NTS); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLExecDirect Failed\n"); /* On se deconnecte avant de quitter */ status = SQLDisconnect(connection_handle); if ((status != SQL_SUCCESS) && (status != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "SQLDisconnect failed\n"); SQLGetDiagRec(SQL_HANDLE_DBC, connection_handle, REC_NUMBER, state, &odbc_error, error_text, BUFFER_LEN, &error_text_len); fprintf(stderr, "%s (error number : %d)\n", error_text, (int)odbc_error); } SQLFreeHandle(SQL_HANDLE_STMT, statment_handle); SQLFreeHandle(SQL_HANDLE_DBC, connection_handle); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return KO; } SQLNumResultCols(statment_handle, &columns); /* Etape 5. recuperer les resultats de la requete */ while(SQL_NO_DATA != (status = SQLFetch(statment_handle))) { for (i = 1; i <= columns; i++) { /* On recupere le buffer de chaque ligne du resultat */ ret = SQLGetData(statment_handle, i, SQL_C_CHAR, result_buffer, sizeof(result_buffer), NULL); if (ret == SQL_SUCCESS) { fprintf(stdout, "%s | ", result_buffer); } } fprintf(stdout, "\n"); } SQLFreeHandle(SQL_HANDLE_STMT, statment_handle); SQLFreeHandle(SQL_HANDLE_DBC, connection_handle); SQLFreeHandle(SQL_HANDLE_ENV, environment_handle); return OK; } int main(int argc, char **argv) { if (argc != 4) { fprintf(stdout, "Usage : %s dataSource user password\n", argv[0]); return KO; } odbc_connection(argv[1], argv[2], argv[3]); return OK; }
Ce programme execute la procedure sp_clearstats, dans ce cas il faut utiliser le driver ODBC natif de Sybase (libsybdrvodb.so). Le driver fourni par FreeTDS ne permet que l’execution des requetes standards (SELECT, INSERT, UPADTE, CREATE, …etc)
Qu’on compile et execute comme suit :
toc@tocNewServer:~/toc_src/DATABASES/Sybase$ gcc -Wall hello-sybase-odbc.c -o hello-sybase-odbc -lodbc toc@tocNewServer:~/toc_src/DATABASES/Sybase$ ./hello-sybase-odbc Sybase tarek 123456 Connection to DataSource Sybase succeeded Database name : SQL Server Database version : 15.7.0 sa | Jun 26 2013 | 0 | 0.0000% | 0 | 0.0000% | probe | Jun 26 2013 | 0 | 0.0000% | 0 | 0.0000% | jstask | Jun 26 2013 | 0 | 0.0000% | 0 | 0.0000% | tarek | Jun 26 2013 | 0 | 0.0000% | 3 | 100.0000% |
savez-vous comment se connecter en utilisant la machine x86_64 ?
Bonjour jubin,
Ici j’ai mis uniquement comment on y accède a partir d’un Linux 32 bits (car Sybase ne supporte plus de façon gratuite cette architecture), pour y accéder a partir d’une machine 64 bits c’est plus simple il suffit de suivre le tuto d’install de Sybase et normalement tu trouveras le Driver ODBC dans le répertoire : /opt/sybase/DataAccess64/ODBC/lib/libsybdrvodb.so (moi j’ai installé sybase dans /opt/sybase).