From 80bcff3d6d1a50dee340efc69c81ab86628fbda2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Tue, 20 Nov 2007 17:01:25 +0000 Subject: [PATCH] Using runtime load of dynamic mysql library (prevents problems with openssl), it requires shared version which isn't available for SLC3. --- org.glite.lbjp-common.db/Makefile | 36 ++--- org.glite.lbjp-common.db/examples/db_test.c | 7 + org.glite.lbjp-common.db/interface/db.h | 3 +- org.glite.lbjp-common.db/src/db.c | 198 ++++++++++++++++++++++------ 4 files changed, 184 insertions(+), 60 deletions(-) diff --git a/org.glite.lbjp-common.db/Makefile b/org.glite.lbjp-common.db/Makefile index e1d093f..bf0dbca 100644 --- a/org.glite.lbjp-common.db/Makefile +++ b/org.glite.lbjp-common.db/Makefile @@ -26,13 +26,27 @@ VPATH=${top_srcdir}/interface:${top_srcdir}/src:${top_srcdir}/examples DEBUG:=-g -O0 -W -Wall +archlib:=lib +host_cpu:=${shell uname -m} +ifeq (${host_cpu},x86_64) + archlib:=lib64 +endif +ifeq ($(shell test -f ${mysql_prefix}/${archlib}/libmysqlclient.so && echo ok),ok) + MYSQL_LIBPATH := ${mysql_prefix}/${archlib}/libmysqlclient.so +endif +ifeq ($(shell test -f ${mysql_prefix}/${archlib}/mysql/libmysqlclient.so && echo ok),ok) + MYSQL_LIBPATH := ${mysql_prefix}/${archlib}/mysql/libmysqlclient.so +endif +MYSQL_CPPFLAGS:=-I${mysql_prefix}/include -I${mysql_prefix}/include/mysql -DMYSQL_LIBPATH=\"${MYSQL_LIBPATH}\" +MYSQL_LIBS=-lz + CFLAGS:= \ ${DEBUG} \ -DVERSION=\"${version}\" \ -I${stagedir}/include -I${top_srcdir}/src -I. \ -I${top_srcdir}/interface \ ${COVERAGE_FLAGS} \ - -I${mysql_prefix}/include -I${mysql_prefix}/include/mysql \ + ${MYSQL_CPPFLAGS} \ -D_GNU_SOURCE ifdef LBS_DB_PROFILE @@ -48,21 +62,7 @@ COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/lib ${LDFLAGS} INSTALL:=libtool --mode=install install -archlib:=lib -host_cpu:=${shell uname -m} -ifeq (${host_cpu},x86_64) - archlib:=lib64 -endif - -ifneq (${mysql_prefix},/usr) - ifeq ($(shell echo ${mysql_version} | cut -d. -f1,2),4.1) - mysqlib := -L${mysql_prefix}/${archlib}/mysql - else - mysqlib := -L${mysql_prefix}/${archlib} - endif -endif - -EXT_LIBS:=${mysqlib} -lmysqlclient -lz -lglite_lbu_trio +EXT_LIBS:=${MYSQL_LIBS} -lglite_lbu_trio -lpthread -ldl OBJS:=db.o TESTOBJS:=dbtest.o HDRS:=db.h @@ -72,6 +72,10 @@ LTESTOBJS:=${TESTOBJS:.o=.lo} default all: compile doc libglite_lbu_db.la: ${LOBJS} + if [ -z "${MYSQL_LIBPATH}" ]; then \ + echo "MySQL shared library not found!"; \ + exit 1; \ + fi ${LINK} -o $@ $< ${EXT_LIBS} libglite_lbu_dbtest.la: ${LTESTOBJS} diff --git a/org.glite.lbjp-common.db/examples/db_test.c b/org.glite.lbjp-common.db/examples/db_test.c index b86338e..d32e4a3 100644 --- a/org.glite.lbjp-common.db/examples/db_test.c +++ b/org.glite.lbjp-common.db/examples/db_test.c @@ -189,6 +189,13 @@ failcon: dprintf(("closing...\n")); glite_lbu_DBClose(ctx); failctx: + { + char *t, *d; + + glite_lbu_DBError(ctx, &t, &d); + printf("Error %s: %s\n", t, d); + free(t); free(d); + } glite_lbu_FreeDBContext(ctx); fail: free(cmd); diff --git a/org.glite.lbjp-common.db/interface/db.h b/org.glite.lbjp-common.db/interface/db.h index 233c8c3..f968bc2 100644 --- a/org.glite.lbjp-common.db/interface/db.h +++ b/org.glite.lbjp-common.db/interface/db.h @@ -306,7 +306,8 @@ int glite_lbu_PrepareStmt(glite_lbu_DBContext ctx, const char *sql, glite_lbu_St /** - * Execute prepared SQL statement. + * Bind input parameters and execute prepared SQL statement. + * Results can be fetched via glite_lbu_FetchRow. * * \param[in,out] stmt SQL statement * \param[in] n number of items diff --git a/org.glite.lbjp-common.db/src/db.c b/org.glite.lbjp-common.db/src/db.c index c9b21b7..6b29fc9 100644 --- a/org.glite.lbjp-common.db/src/db.c +++ b/org.glite.lbjp-common.db/src/db.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -25,15 +27,18 @@ #define GLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH 256 #endif - #define CLR_ERR(CTX) lbu_clrerr((CTX)) -#define ERR(CTX, CODE, DESC) lbu_err((CTX), (CODE), (DESC), __FUNCTION__, __LINE__) +#define ERR(CTX, CODE, ARGS...) lbu_err((CTX), (CODE), __FUNCTION__, __LINE__, ##ARGS) #define STATUS(CTX) ((CTX)->err.code) #define MY_ERR(CTX) myerr((CTX), __FUNCTION__, __LINE__) #define MY_ERRSTMT(STMT) myerrstmt((STMT), __FUNCTION__, __LINE__) #define MY_ISOKSTMT(STMT, RETRY) myisokstmt((STMT), __FUNCTION__, __LINE__, (RETRY)) #define USE_TRANS(CTX) ((CTX->caps & GLITE_LBU_DB_CAP_TRANSACTIONS) != 0) +#define LOAD(SYM, SYM2) if ((*(void **)(&db_handle.SYM) = dlsym(db_handle.lib, SYM2)) == NULL) { \ + err = ERR(ctx, ENOENT, "can't load symbol %s from mysql library (%s)", SYM2, dlerror()); \ + break; \ +} #define dprintf(CTX, FMT...) if (CTX->caps & GLITE_LBU_DB_CAP_ERRORS) fprintf(stderr, ##FMT) @@ -99,9 +104,50 @@ int glite_type_to_mysql[] = { }; +typedef struct { + void *lib; + pthread_mutex_t lock; + + void *(*mysql_init)(void *); + int (*mysql_options)(MYSQL *mysql, enum mysql_option option, const char *arg); + unsigned int (*mysql_errno)(MYSQL *mysql); + const char *(*mysql_error)(MYSQL *mysql); + unsigned int (*mysql_stmt_errno)(MYSQL_STMT *stmt); + const char *(*mysql_stmt_error)(MYSQL_STMT *stmt); + MYSQL *(*mysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag); + void (*mysql_close)(MYSQL *mysql); + int (*mysql_query)(MYSQL *mysql, const char *stmt_str); + MYSQL_RES *(*mysql_store_result)(MYSQL *mysql); + void (*mysql_free_result)(MYSQL_RES *result); + my_ulonglong (*mysql_affected_rows)(MYSQL *mysql); + my_bool (*mysql_stmt_close)(MYSQL_STMT *); + unsigned int (*mysql_num_fields)(MYSQL_RES *result); + unsigned long *(*mysql_fetch_lengths)(MYSQL_RES *result); + my_bool (*mysql_stmt_bind_result)(MYSQL_STMT *stmt, MYSQL_BIND *bind); + int (*mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *stmt_str, unsigned long length); + int (*mysql_stmt_store_result)(MYSQL_STMT *stmt); + MYSQL_ROW (*mysql_fetch_row)(MYSQL_RES *result); + MYSQL_FIELD *(*mysql_fetch_field)(MYSQL_RES *result); + const char *(*mysql_get_server_info)(MYSQL *mysql); + MYSQL_STMT *(*mysql_stmt_init)(MYSQL *mysql); + my_bool (*mysql_stmt_bind_param)(MYSQL_STMT *stmt, MYSQL_BIND *bind); + int (*mysql_stmt_execute)(MYSQL_STMT *stmt); + int (*mysql_stmt_fetch)(MYSQL_STMT *stmt); + my_ulonglong (*mysql_stmt_insert_id)(MYSQL_STMT *stmt); + my_ulonglong (*mysql_stmt_affected_rows)(MYSQL_STMT *stmt); + MYSQL_RES *(*mysql_stmt_result_metadata)(MYSQL_STMT *stmt); + int (*mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset); +} mysql_lib_handle_t; + + +static mysql_lib_handle_t db_handle = { + lib: NULL, + lock: PTHREAD_MUTEX_INITIALIZER +}; + static int lbu_clrerr(glite_lbu_DBContext ctx); -static int lbu_err(glite_lbu_DBContext ctx, int code, const char *desc, const char *func, int line); +static int lbu_err(glite_lbu_DBContext ctx, int code, const char *func, int line, const char *desc, ...); static int myerr(glite_lbu_DBContext ctx, const char *source, int line); static int myerrstmt(glite_lbu_Statement stmt, const char *source, int line); static int myisokstmt(glite_lbu_Statement stmt, const char *source, int line, int *retry); @@ -142,7 +188,66 @@ void glite_lbu_FreeDBContext(glite_lbu_DBContext ctx) { } +static void glite_lbu_DBCleanup(void) { + pthread_mutex_lock(&db_handle.lock); + if (db_handle.lib) { + dlclose(db_handle.lib); + db_handle.lib = NULL; + } + pthread_mutex_unlock(&db_handle.lock); +} + + int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { + int err = 0; + + /* dynamic load the mysql library */ + pthread_mutex_lock(&db_handle.lock); + if (!db_handle.lib) { + if ((!MYSQL_LIBPATH[0] || (db_handle.lib = dlopen(MYSQL_LIBPATH, RTLD_LAZY | RTLD_LOCAL)) == NULL) && + (db_handle.lib = dlopen("libmysqlclient.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) + return ERR(ctx, ENOENT, "can't load '%s' or 'libmysqlclient.so' (%s)", MYSQL_LIBPATH, dlerror()); + do { + LOAD(mysql_init, "mysql_init"); + LOAD(mysql_options, "mysql_options"); + LOAD(mysql_errno, "mysql_errno"); + LOAD(mysql_error, "mysql_error"); + LOAD(mysql_stmt_errno, "mysql_stmt_errno"); + LOAD(mysql_stmt_error, "mysql_stmt_error"); + LOAD(mysql_real_connect, "mysql_real_connect"); + LOAD(mysql_close, "mysql_close"); + LOAD(mysql_query, "mysql_query"); + LOAD(mysql_store_result, "mysql_store_result"); + LOAD(mysql_free_result, "mysql_free_result"); + LOAD(mysql_affected_rows, "mysql_affected_rows"); + LOAD(mysql_stmt_close, "mysql_stmt_close"); + LOAD(mysql_num_fields, "mysql_num_fields"); + LOAD(mysql_fetch_lengths, "mysql_fetch_lengths"); + LOAD(mysql_stmt_bind_result, "mysql_stmt_bind_result"); + LOAD(mysql_stmt_prepare, "mysql_stmt_prepare"); + LOAD(mysql_stmt_store_result, "mysql_stmt_store_result"); + LOAD(mysql_fetch_row, "mysql_fetch_row"); + LOAD(mysql_fetch_field, "mysql_fetch_field"); + LOAD(mysql_get_server_info, "mysql_get_server_info"); + LOAD(mysql_stmt_init, "mysql_stmt_init"); + LOAD(mysql_stmt_bind_param, "mysql_stmt_bind_param"); + LOAD(mysql_stmt_execute, "mysql_stmt_execute"); + LOAD(mysql_stmt_fetch, "mysql_stmt_fetch"); + LOAD(mysql_stmt_insert_id, "mysql_stmt_insert_id"); + LOAD(mysql_stmt_affected_rows, "mysql_stmt_affected_rows"); + LOAD(mysql_stmt_result_metadata, "mysql_stmt_result_metadata"); + LOAD(mysql_stmt_fetch_column, "mysql_stmt_fetch_column"); + pthread_mutex_unlock(&db_handle.lock); + atexit(glite_lbu_DBCleanup); + } while(0); + if (err) { + dlclose(db_handle.lib); + db_handle.lib = NULL; + pthread_mutex_unlock(&db_handle.lock); + return err; + } + } else pthread_mutex_unlock(&db_handle.lock); + if (db_connect(ctx, cs, &ctx->mysql) != 0) return STATUS(ctx); return 0; } @@ -163,7 +268,7 @@ int glite_lbu_DBQueryCaps(glite_lbu_DBContext ctx) { origcaps = ctx->caps; caps = 0; - ver_s = mysql_get_server_info(m); + ver_s = db_handle.mysql_get_server_info(m); if (!ver_s || 3 != sscanf(ver_s,"%d.%d.%d",&major,&minor,&sub)) return ERR(ctx, EINVAL, "problem retreiving MySQL version"); version = 10000*major + 100*minor + sub; @@ -228,8 +333,8 @@ int glite_lbu_FetchRow(glite_lbu_Statement stmt, unsigned int n, unsigned long * void glite_lbu_FreeStmt(glite_lbu_Statement *stmt) { if (*stmt) { - if ((*stmt)->result) mysql_free_result((*stmt)->result); - if ((*stmt)->stmt) mysql_stmt_close((*stmt)->stmt); + if ((*stmt)->result) db_handle.mysql_free_result((*stmt)->result); + if ((*stmt)->stmt) db_handle.mysql_stmt_close((*stmt)->stmt); free(*stmt); *stmt = NULL; } @@ -356,13 +461,13 @@ int glite_lbu_ExecSQL(glite_lbu_DBContext ctx, const char *cmd, glite_lbu_Statem while (retry_nr == 0 || do_reconnect) { do_reconnect = 0; - if (mysql_query(ctx->mysql, cmd)) { + if (db_handle.mysql_query(ctx->mysql, cmd)) { /* error occured */ - switch (merr = mysql_errno(ctx->mysql)) { + switch (merr = db_handle.mysql_errno(ctx->mysql)) { case 0: break; case ER_DUP_ENTRY: - ERR(ctx, EEXIST, mysql_error(ctx->mysql)); + ERR(ctx, EEXIST, db_handle.mysql_error(ctx->mysql)); return -1; break; case CR_SERVER_LOST: @@ -386,17 +491,17 @@ int glite_lbu_ExecSQL(glite_lbu_DBContext ctx, const char *cmd, glite_lbu_Statem return -1; } (**stmt).ctx = ctx; - (**stmt).result = mysql_store_result(ctx->mysql); + (**stmt).result = db_handle.mysql_store_result(ctx->mysql); if (!(**stmt).result) { - if (mysql_errno(ctx->mysql)) { + if (db_handle.mysql_errno(ctx->mysql)) { MY_ERR(ctx); *stmt = NULL; return -1; } } } else { - MYSQL_RES *r = mysql_store_result(ctx->mysql); - mysql_free_result(r); + MYSQL_RES *r = db_handle.mysql_store_result(ctx->mysql); + db_handle.mysql_free_result(r); } #ifdef LBS_DB_PROFILE pid = getpid(); @@ -411,7 +516,7 @@ int glite_lbu_ExecSQL(glite_lbu_DBContext ctx, const char *cmd, glite_lbu_Statem fprintf(stderr,"[%d] %s\n[%d] %3ld.%06ld (sum: %3ld.%06ld)\n",pid,txt,pid,end.tv_sec,end.tv_usec,sum.tv_sec,sum.tv_usec); #endif - return mysql_affected_rows(ctx->mysql); + return db_handle.mysql_affected_rows(ctx->mysql); } @@ -422,7 +527,7 @@ int glite_lbu_QueryColumns(glite_lbu_Statement stmt, char **cols) CLR_ERR(stmt->ctx); if (!stmt->result) return ERR(stmt->ctx, EINVAL, "QueryColumns implemented only for simple API"); - while ((f = mysql_fetch_field(stmt->result))) cols[i++] = f->name; + while ((f = db_handle.mysql_fetch_field(stmt->result))) cols[i++] = f->name; return i == 0; } @@ -460,21 +565,21 @@ int glite_lbu_PrepareStmt(glite_lbu_DBContext ctx, const char *sql, glite_lbu_St (*stmt)->ctx = ctx; // create the SQL command - if (((*stmt)->stmt = mysql_stmt_init(ctx->mysql)) == NULL) + if (((*stmt)->stmt = db_handle.mysql_stmt_init(ctx->mysql)) == NULL) return MY_ERRSTMT(*stmt); // prepare the SQL command retry = 1; do { - mysql_stmt_prepare((*stmt)->stmt, sql, strlen(sql)); + db_handle.mysql_stmt_prepare((*stmt)->stmt, sql, strlen(sql)); ret = MY_ISOKSTMT(*stmt, &retry); } while (ret == 0); if (ret == -1) goto failed; // number of fields (0 for no results) - if ((meta = mysql_stmt_result_metadata((*stmt)->stmt)) != NULL) { - (*stmt)->nrfields = mysql_num_fields(meta); - mysql_free_result(meta); + if ((meta = db_handle.mysql_stmt_result_metadata((*stmt)->stmt)) != NULL) { + (*stmt)->nrfields = db_handle.mysql_num_fields(meta); + db_handle.mysql_free_result(meta); } else (*stmt)->nrfields = 0; @@ -559,7 +664,7 @@ int glite_lbu_ExecPreparedStmt(glite_lbu_Statement stmt, int n, ...) { va_end(ap); // bind parameters - if (mysql_stmt_bind_param(stmt->stmt, binds) != 0) { + if (db_handle.mysql_stmt_bind_param(stmt->stmt, binds) != 0) { MY_ERRSTMT(stmt); goto failed; } @@ -568,7 +673,7 @@ int glite_lbu_ExecPreparedStmt(glite_lbu_Statement stmt, int n, ...) { ctx = stmt->ctx; retry = 1; do { - mysql_stmt_execute(stmt->stmt); + db_handle.mysql_stmt_execute(stmt->stmt); ret = MY_ISOKSTMT(stmt, &retry); } while (ret == 0); if (ret == -1) goto failed; @@ -576,7 +681,7 @@ int glite_lbu_ExecPreparedStmt(glite_lbu_Statement stmt, int n, ...) { // result retry = 1; do { - mysql_stmt_store_result(stmt->stmt); + db_handle.mysql_stmt_store_result(stmt->stmt); ret = MY_ISOKSTMT(stmt, &retry); } while (ret == 0); if (ret == -1) goto failed; @@ -587,7 +692,7 @@ int glite_lbu_ExecPreparedStmt(glite_lbu_Statement stmt, int n, ...) { free(binds); free(lens); CLR_ERR(ctx); - return mysql_stmt_affected_rows(stmt->stmt); + return db_handle.mysql_stmt_affected_rows(stmt->stmt); failed: for (i = 0; i < n; i++) free(data[i]); @@ -693,7 +798,7 @@ long int glite_lbu_Lastid(glite_lbu_Statement stmt) { my_ulonglong i; CLR_ERR(stmt->ctx); - i = mysql_stmt_insert_id(stmt->stmt); + i = db_handle.mysql_stmt_insert_id(stmt->stmt); assert(i < ((unsigned long int)-1) >> 1); return (long int)i; } @@ -715,11 +820,18 @@ static int lbu_clrerr(glite_lbu_DBContext ctx) { /* * helping compatibility function: sets error on the context */ -static int lbu_err(glite_lbu_DBContext ctx, int code, const char *desc, const char *func, int line) { +static int lbu_err(glite_lbu_DBContext ctx, int code, const char *func, int line, const char *desc, ...) { + va_list ap; + if (code) { ctx->err.code = code; free(ctx->err.desc); - ctx->err.desc = desc ? strdup(desc) : NULL; + if (desc) { + va_start(ap, desc); + vasprintf(&ctx->err.desc, desc, ap); + va_end(ap); + } else + ctx->err.desc = NULL; dprintf(ctx, "[db %d] %s:%d %s\n", getpid(), func, line, desc); return code; } else @@ -731,7 +843,7 @@ static int lbu_err(glite_lbu_DBContext ctx, int code, const char *desc, const ch * helping function: find oud mysql error and sets on the context */ static int myerr(glite_lbu_DBContext ctx, const char *source, int line) { - return lbu_err(ctx, EIO, mysql_error(ctx->mysql), source, line); + return lbu_err(ctx, EIO, source, line, db_handle.mysql_error(ctx->mysql)); } @@ -739,7 +851,7 @@ static int myerr(glite_lbu_DBContext ctx, const char *source, int line) { * helping function: find oud mysql stmt error and sets on the context */ static int myerrstmt(glite_lbu_Statement stmt, const char *source, int line) { - return lbu_err(stmt->ctx, EIO, mysql_stmt_error(stmt->stmt), source, line); + return lbu_err(stmt->ctx, EIO, source, line, db_handle.mysql_stmt_error(stmt->stmt)); } @@ -751,12 +863,12 @@ static int myerrstmt(glite_lbu_Statement stmt, const char *source, int line) { * \return 1 OK */ static int myisokstmt(glite_lbu_Statement stmt, const char *source, int line, int *retry) { - switch (mysql_stmt_errno(stmt->stmt)) { + switch (db_handle.mysql_stmt_errno(stmt->stmt)) { case 0: return 1; break; case ER_DUP_ENTRY: - lbu_err(stmt->ctx, EEXIST, mysql_stmt_error(stmt->stmt), source, line); + lbu_err(stmt->ctx, EEXIST, source, line, db_handle.mysql_stmt_error(stmt->stmt)); return -1; break; case CR_SERVER_LOST: @@ -794,12 +906,12 @@ static int db_connect(glite_lbu_DBContext ctx, const char *cs, MYSQL **mysql) { if (!cs) return ERR(ctx, EINVAL, "connect string not specified"); - if (!(*mysql = mysql_init(NULL))) return ERR(ctx, ENOMEM, NULL); + if (!(*mysql = db_handle.mysql_init(NULL))) return ERR(ctx, ENOMEM, NULL); - mysql_options(*mysql, MYSQL_READ_DEFAULT_FILE, "my"); + db_handle.mysql_options(*mysql, MYSQL_READ_DEFAULT_FILE, "my"); #ifdef MYSQL_OPT_RECONNECT /* XXX: may result in weird behaviour in the middle of transaction */ - mysql_options(*mysql, MYSQL_OPT_RECONNECT, &reconnect); + db_handle.mysql_options(*mysql, MYSQL_OPT_RECONNECT, &reconnect); #endif host = user = pw = db = NULL; @@ -825,7 +937,7 @@ static int db_connect(glite_lbu_DBContext ctx, const char *cs, MYSQL **mysql) { /* ljocha: CLIENT_FOUND_ROWS added to make authorization check * working in update_notif(). * Hope it does not break anything else */ - if (!mysql_real_connect(*mysql,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) { + if (!db_handle.mysql_real_connect(*mysql,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) { free(buf); ret = MY_ERR(ctx); glite_lbu_DBClose(ctx); @@ -842,7 +954,7 @@ static int db_connect(glite_lbu_DBContext ctx, const char *cs, MYSQL **mysql) { * mysql close */ static void db_close(MYSQL *mysql) { - if (mysql) mysql_close(mysql); + if (mysql) db_handle.mysql_close(mysql); } @@ -888,15 +1000,15 @@ static int FetchRowSimple(glite_lbu_DBContext ctx, MYSQL_RES *result, unsigned l CLR_ERR(ctx); - if (!(row = mysql_fetch_row(result))) { - if (mysql_errno((MYSQL *) ctx->mysql)) { + if (!(row = db_handle.mysql_fetch_row(result))) { + if (db_handle.mysql_errno((MYSQL *) ctx->mysql)) { MY_ERR(ctx); return -1; } else return 0; } - nr = mysql_num_fields(result); - len = mysql_fetch_lengths(result); + nr = db_handle.mysql_num_fields(result); + len = db_handle.mysql_fetch_lengths(result); for (i=0; istmt, binds) != 0) goto failedstmt; + if (db_handle.mysql_stmt_bind_result(stmt->stmt, binds) != 0) goto failedstmt; // fetch data, all can be truncated retry = 1; do { - switch(mysql_stmt_fetch(stmt->stmt)) { + switch(db_handle.mysql_stmt_fetch(stmt->stmt)) { #ifdef MYSQL_DATA_TRUNCATED case MYSQL_DATA_TRUNCATED: #endif @@ -972,7 +1084,7 @@ static int FetchRowPrepared(glite_lbu_DBContext ctx, glite_lbu_Statement stmt, u retry = 1; do { - switch (mysql_stmt_fetch_column(stmt->stmt, binds + i, i, fetched)) { + switch (db_handle.mysql_stmt_fetch_column(stmt->stmt, binds + i, i, fetched)) { case 0: ret = 1; break; case 1: ret = MY_ISOKSTMT(stmt, &retry); break; case MYSQL_NO_DATA: ret = 0; goto quit; /* it's OK */ -- 1.8.2.3