#include #include #include #include #include static void odbc_sqlerror(SQLSMALLINT type, SQLHANDLE handle){ SQLCHAR state[7]; SQLCHAR text[1024]; SQLSMALLINT len; int i=0; SQLINTEGER native; while( SQL_SUCCEEDED(SQLGetDiagRec(type, handle, ++i, state, &native, text, sizeof(text), &len))) { fprintf(stderr, "(%d) %s:%ld:%s\n", i, state, native, text); } } static SQLHDBC new_hdbc(const char *db, SQLHENV henv){ SQLRETURN retcode; SQLHDBC hdbc; retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_DBC, hdbc); return NULL; } retcode = SQLConnect(hdbc, (char*)db, SQL_NTS, NULL, 0, NULL, 0); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); return NULL; } return hdbc; } static void free_hdbc(SQLHDBC hdbc){ int retcode; retcode = SQLDisconnect(hdbc); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_DBC, hdbc); } SQLFreeHandle(SQL_HANDLE_DBC, hdbc); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_DBC, hdbc); } } static SQLHENV new_henv(void){ SQLHENV henv; SQLRETURN retcode; retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_ENV, henv); return NULL; } SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); return henv; } static void free_henv(SQLHDBC henv){ int retcode; retcode = SQLFreeHandle(SQL_HANDLE_ENV, henv); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) { odbc_sqlerror(SQL_HANDLE_ENV, henv); } } void *routine(void *arg){ #define NB_CNX 6 SQLHENV henv; SQLHDBC hdbc[NB_CNX]; int i; int j; int release_henv = 0; henv = (SQLHENV)arg; if (henv == NULL) { release_henv = 1; if ((henv = new_henv()) == NULL) { return NULL; } } for (i = 0; i < NB_CNX; i++) { printf("Thread %x: opening connection %d\n", pthread_self(), i); if ((hdbc[i] = new_hdbc("DB", henv)) == NULL) { return NULL; } } for (i = 0; i < NB_CNX; i++) { printf("Thread %x: closing connection %d\n", pthread_self(), i); free_hdbc(hdbc[i]); } if (release_henv) { free_henv(henv); } return NULL; } int main(){ #define NB_THREAD 10 pthread_t thread[NB_THREAD]; int i; struct timeval tv; SQLHENV henv; /* setting this variable to 1 will force the program to use only one SQLHENV allocated in the main program. however if set to 0 the program will allocate an SQLHENV in each thread */ int one_henv = 0; if (one_henv) { if ((henv = new_henv()) == NULL) { return 0; } } for (i = 0; i < NB_THREAD; i++) { pthread_create(&thread[i], NULL, routine, (one_henv) ? henv : NULL); } for (i = 0; i < NB_THREAD; i++) { pthread_join(thread[i], NULL); } if (one_henv) { free_henv(henv); } }