From 53469228b8220a79fadee724bc67e2dbacc7d1bc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Thu, 10 Aug 2006 23:37:04 +0000 Subject: [PATCH] Various improvements and fixes of the new DB module: - used basic error handling - fixes due to tests with LB - library renamed - first shot of index support --- org.glite.lb-utils.db/Makefile | 12 +-- org.glite.lb-utils.db/interface/db.h | 37 ++++--- org.glite.lb-utils.db/src/db.c | 198 +++++++++++++++++++++++++++-------- 3 files changed, 183 insertions(+), 64 deletions(-) diff --git a/org.glite.lb-utils.db/Makefile b/org.glite.lb-utils.db/Makefile index 43320d3..d97f2df 100644 --- a/org.glite.lb-utils.db/Makefile +++ b/org.glite.lb-utils.db/Makefile @@ -65,21 +65,21 @@ HDRS:=db.h LOBJS:=${OBJS:.o=.lo} LTESTOBJS:=${TESTOBJS:.o=.lo} -libglite_lbutils_db.la: ${LOBJS} +libglite_lbu_db.la: ${LOBJS} ${LINK} -o $@ $< ${EXT_LIBS} -libglite_lbutils_dbtest.la: ${LTESTOBJS} +libglite_lbu_dbtest.la: ${LTESTOBJS} ${LINK} -o $@ $< ${EXT_LIBS} dbtest.lo dbtest.o: db.c db.h ${COMPILE} -DGLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH=10 -c $< -o $@ -db_test: db_test.lo libglite_lbutils_dbtest.la +db_test: db_test.lo libglite_lbu_dbtest.la ${LINK} -o $@ $+ ${EXT_LIBS} default all: compile -compile: libglite_lbutils_db.la +compile: libglite_lbu_db.la check: -echo No checks here yet. @@ -114,7 +114,7 @@ install: -mkdir -p ${PREFIX}/lib -mkdir -p ${PREFIX}/include/${globalprefix}/${lbutilsprefix} # ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} - ${INSTALL} -m 755 "libglite_lbutils_db.la" "${PREFIX}/lib/glite-lbutils-db.la"; \ + ${INSTALL} -m 755 "libglite_lbu_db.la" "${PREFIX}/lib/libglite_lbu_db.la"; \ ${INSTALL} -m 644 ${top_srcdir}/interface/${HDRS} ${PREFIX}/include/${globalprefix}/${lbutilsprefix} clean: @@ -123,6 +123,6 @@ clean: ${COMPILE} -c $< db.lo: db.c db.h -db_test.lo: libglite_lbutils_dbtest.la db.h db_test.c +db_test.lo: libglite_lbu_dbtest.la db.h db_test.c .PHONY: default all compile check examples doc stage dist distsrc distbin install clean test_coverage diff --git a/org.glite.lb-utils.db/interface/db.h b/org.glite.lb-utils.db/interface/db.h index 3640dc9..d1ac8e7 100644 --- a/org.glite.lb-utils.db/interface/db.h +++ b/org.glite.lb-utils.db/interface/db.h @@ -3,6 +3,10 @@ #ident "$Header$" + +#include + + #ifdef __cplusplus extern "C" { #endif @@ -60,7 +64,7 @@ typedef struct glite_lbu_Statement_s *glite_lbu_Statement; /** * Structure holds date for multi-rows insert. */ -typedef struct glite_lbu_bufInsert_s glite_lbu_bufInsert; +typedef struct glite_lbu_bufInsert_s *glite_lbu_bufInsert; @@ -91,6 +95,16 @@ typedef enum { /** + * Get error state from DB context. + * + * \param[in] ctx context to work with + * \param[out] text error name + * \param[out] desc error description + */ +int glite_lbu_DBError(glite_lbu_DBContext ctx, char **text, char **desc); + + +/** * Create the context and connect to the database. * * \param[out] ctx context to work with @@ -167,9 +181,11 @@ int glite_lbu_FetchRow(glite_lbu_Statement stmt, unsigned int n, unsigned long * /** * Free the statement structure and destroy its parameters. * + * Statement will be set to NULL and multiple calls are allowed. + * * \param[in,out] stmt statement */ -void glite_lbu_FreeStmt(glite_lbu_Statement stmt); +void glite_lbu_FreeStmt(glite_lbu_Statement *stmt); /** @@ -201,15 +217,14 @@ int glite_lbu_QueryColumns(glite_lbu_Statement stmt, char **cols); /** * Retrieve column names of a query simple SQL statement. * - * Not implemented for now. - * - * \param[in,out] ctx context to work with - * \param[in] table table name - * \param[out] names result set column names. Expects allocated array. + * \param[in,out] ctx context to work with + * \param[in] table table name + * \param[out] key_names one-dimensional index names array + * \param[out] column_names two-dimensional column names array * * \return 0 if OK, nonzero on error */ -int glite_lbu_QueryIndices(glite_lbu_DBContext ctx, const char *table, char ***names); +int glite_lbu_QueryIndices(glite_lbu_DBContext ctx, const char *table, char ***key_names, char ****column_names); /** @@ -249,13 +264,13 @@ int glite_lbu_bufferedInsertInit(glite_lbu_DBContext ctx, glite_lbu_bufInsert *b * if num. of rows or size of data oversteps the limits, real * multi-row insert is done */ -int glite_lbu_bufferedInsert(glite_lbu_bufInsert *bi, const char *row); +int glite_lbu_bufferedInsert(glite_lbu_bufInsert bi, const char *row); /** * Flush buffered data and free bi structure. */ -int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert *bi); +int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert bi); /** @@ -306,6 +321,4 @@ int glite_lbu_ExecStmt(glite_lbu_Statement stmt, int n, ...); } #endif -#else -#error Already included #endif diff --git a/org.glite.lb-utils.db/src/db.c b/org.glite.lb-utils.db/src/db.c index f65a004..36a62b1 100644 --- a/org.glite.lb-utils.db/src/db.c +++ b/org.glite.lb-utils.db/src/db.c @@ -29,7 +29,7 @@ #define CLR_ERR(CTX) lbu_clrerr((CTX)) #define ERR(CTX, CODE, DESC) lbu_err((CTX), (CODE), (DESC), __FUNCTION__, __LINE__) -#define STATUS(CTX) ((CTX)->code) +#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)) @@ -41,9 +41,12 @@ struct glite_lbu_DBContext_s { MYSQL *mysql; const char *cs; + int have_caps; int caps; - int code; - char *text; + struct { + int code; + char *desc; + } err; }; @@ -99,7 +102,7 @@ int glite_type_to_mysql[] = { static int lbu_clrerr(glite_lbu_DBContext ctx); -static int lbu_err(glite_lbu_DBContext ctx, int code, const char *text, const char *func, int line); +static int lbu_err(glite_lbu_DBContext ctx, int code, const char *desc, const char *func, int line); 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); @@ -115,6 +118,17 @@ time_t get_time(const MYSQL_TIME *mtime); /* ---- common ---- */ +int glite_lbu_DBError(glite_lbu_DBContext ctx, char **text, char **desc) { + if (text) *text = strdup(strerror(ctx->err.code)); + if (desc) { + if (ctx->err.desc) *desc = strdup(ctx->err.desc); + else *desc = NULL; + } + + return ctx->err.code; +} + + int glite_lbu_DBConnect(glite_lbu_DBContext *ctx, const char *cs, int caps) { int err; @@ -131,7 +145,7 @@ int glite_lbu_DBConnect(glite_lbu_DBContext *ctx, const char *cs, int caps) { void glite_lbu_DBClose(glite_lbu_DBContext ctx) { db_close(ctx->mysql); - free(ctx->text); + free(ctx->err.desc); free(ctx); } @@ -142,6 +156,8 @@ int glite_lbu_DBQueryCaps(glite_lbu_DBContext ctx) { int major,minor,sub,version,caps,have_transactions=0; const char *ver_s; + if (ctx->have_caps) return ctx->caps; + caps = 0; ver_s = mysql_get_server_info(m); @@ -160,8 +176,10 @@ int glite_lbu_DBQueryCaps(glite_lbu_DBContext ctx) { } if (have_transactions) caps |= GLITE_LBU_DB_CAP_TRANSACTIONS; - if (STATUS(ctx) == 0) return caps; - else return -1; + if (STATUS(ctx) == 0) { + ctx->have_caps = 1; + return caps; + } else return -1; } @@ -201,24 +219,110 @@ err: int glite_lbu_FetchRow(glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results) { + memset(results, 0, n * sizeof(*results)); if (stmt->result) return FetchRowSimple(stmt->ctx, stmt->result, lengths, results); else return FetchRowPrepared(stmt->ctx, stmt, n, lengths, results); } -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); - free(stmt); +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); + free(*stmt); + *stmt = NULL; } } -#warning TODO: glite_lbu_QueryIndices not implemented -/*int glite_lbu_QueryIndices(glite_lbu_DBContext ctx, const char *table, char **names) { - return 0; -}*/ +int glite_lbu_QueryIndices(glite_lbu_DBContext ctx, const char *table, char ***key_names, char ****column_names) { + glite_lbu_Statement stmt = NULL; + + int i,j,ret; + +/* XXX: "show index from" columns. Matches at least MySQL 4.0.11 */ + char *showcol[12]; + int Key_name,Seq_in_index,Column_name,Sub_part; + + char **keys = NULL; + int *cols = NULL; + char **col_names = NULL; + + int nkeys = 0; + + char ***idx = NULL; + + Key_name = Seq_in_index = Column_name = Sub_part = -1; + + if (glite_lbu_ExecSQL(ctx,"show index from states",&stmt)<0) + return STATUS(ctx); + + while ((ret = glite_lbu_FetchRow(stmt,sizeof(showcol)/sizeof(showcol[0]),NULL,showcol)) > 0) { + assert(ret <= sizeof showcol/sizeof showcol[0]); + + if (!col_names) { + col_names = malloc(ret * sizeof col_names[0]); + glite_lbu_QueryColumns(stmt,col_names); + for (i=0; i= 0 && Seq_in_index >= 0 && + Column_name >= 0 && Sub_part >= 0); + + } + + for (i=0; imysql)) { MY_ERR(ctx); + *stmt = NULL; return -1; } } @@ -309,7 +414,7 @@ int glite_lbu_QueryColumns(glite_lbu_Statement stmt, char **cols) int i = 0; MYSQL_FIELD *f; - if (!stmt->result) return ERR(stmt->ctx, EINVAL, "QueryColums work only in simple API"); + 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; return i == 0; } @@ -369,7 +474,7 @@ int glite_lbu_PrepareStmt(glite_lbu_DBContext ctx, const char *sql, glite_lbu_St return CLR_ERR(ctx); failed: - glite_lbu_FreeStmt(*stmt); + glite_lbu_FreeStmt(stmt); return STATUS(ctx); } @@ -488,20 +593,21 @@ failed: int glite_lbu_bufferedInsertInit(glite_lbu_DBContext ctx, glite_lbu_bufInsert *bi, void *mysql, const char *table_name, long size_limit, long record_limit, const char *columns) { - bi->ctx = ctx; - bi->table_name = strdup(table_name); - bi->columns = strdup(columns); - bi->rec_num = 0; - bi->rec_size = 0; - bi->rows = calloc(record_limit, sizeof(*(bi->rows)) ); - bi->size_limit = size_limit; - bi->record_limit = record_limit; - - return STATUS(bi->ctx); + *bi = calloc(1, sizeof(*bi)); + (*bi)->ctx = ctx; + (*bi)->table_name = strdup(table_name); + (*bi)->columns = strdup(columns); + (*bi)->rec_num = 0; + (*bi)->rec_size = 0; + (*bi)->rows = calloc(record_limit, sizeof(*((*bi)->rows)) ); + (*bi)->size_limit = size_limit; + (*bi)->record_limit = record_limit; + + return CLR_ERR(ctx); } -static int flush_bufferd_insert(glite_lbu_bufInsert *bi) +static int flush_bufferd_insert(glite_lbu_bufInsert bi) { char *stmt, *vals, *temp; long i; @@ -538,7 +644,7 @@ static int flush_bufferd_insert(glite_lbu_bufInsert *bi) } -int glite_lbu_bufferedInsert(glite_lbu_bufInsert *bi, const char *row) +int glite_lbu_bufferedInsert(glite_lbu_bufInsert bi, const char *row) { bi->rows[bi->rec_num++] = strdup(row); bi->rec_size += strlen(row); @@ -554,7 +660,7 @@ int glite_lbu_bufferedInsert(glite_lbu_bufInsert *bi, const char *row) } -static void free_buffered_insert(glite_lbu_bufInsert *bi) { +static void free_buffered_insert(glite_lbu_bufInsert bi) { long i; free(bi->table_name); @@ -566,7 +672,7 @@ static void free_buffered_insert(glite_lbu_bufInsert *bi) { } -int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert *bi) +int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert bi) { if (flush_bufferd_insert(bi)) return STATUS(bi->ctx); @@ -580,10 +686,10 @@ int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert *bi) * helping compatibility function: clear error from the context */ static int lbu_clrerr(glite_lbu_DBContext ctx) { - ctx->code = 0; - if (ctx->text) { - free(ctx->text); - ctx->text = NULL; + ctx->err.code = 0; + if (ctx->err.desc) { + free(ctx->err.desc); + ctx->err.desc = NULL; } return 0; } @@ -592,15 +698,15 @@ 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 *text, const char *func, int line) { +static int lbu_err(glite_lbu_DBContext ctx, int code, const char *desc, const char *func, int line) { if (code) { - ctx->code = code; - free(ctx->text); - ctx->text = text ? strdup(text) : NULL; - fprintf(stderr, "[db] %s:%d %s\n", func, line, text); + ctx->err.code = code; + free(ctx->err.desc); + ctx->err.desc = desc ? strdup(desc) : NULL; + fprintf(stderr, "[db] %s:%d %s\n", func, line, desc); return code; } else - return ctx->code; + return ctx->err.code; } @@ -759,11 +865,11 @@ static int transaction_test(glite_lbu_DBContext ctx, MYSQL *m2, int *have_transa *have_transactions = retval == 0; goto ok; err2: - err = ctx->code; - desc = ctx->text; + err = ctx->err.code; + desc = ctx->err.desc; glite_lbu_ExecSQL(ctx, cmd_drop, NULL); - ctx->code = err; - ctx->text = desc; + ctx->err.code = err; + ctx->err.desc = desc; err1: ok: free(cmd_create); -- 1.8.2.3