From f19a009f13538ea84d406812d4782bf8960caf3d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Fri, 8 Jan 2010 11:47:22 +0000 Subject: [PATCH] Revert DB module API changes for branch 2.0, first stage - added/removed files. --- org.glite.lbjp-common.db/interface/db-int.h | 60 -- org.glite.lbjp-common.db/src/db-mysql.c | 1121 --------------------------- org.glite.lbjp-common.db/src/db-pg.c | 603 -------------- org.glite.lbjp-common.db/src/db.c | 396 ---------- 4 files changed, 2180 deletions(-) delete mode 100644 org.glite.lbjp-common.db/interface/db-int.h delete mode 100644 org.glite.lbjp-common.db/src/db-mysql.c delete mode 100644 org.glite.lbjp-common.db/src/db-pg.c delete mode 100644 org.glite.lbjp-common.db/src/db.c diff --git a/org.glite.lbjp-common.db/interface/db-int.h b/org.glite.lbjp-common.db/interface/db-int.h deleted file mode 100644 index 7a86c84..0000000 --- a/org.glite.lbjp-common.db/interface/db-int.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifdef WIN32 -#define asprintf(STR, FMT...) trio_asprintf((STR), ##FMT) -#define vasprintf(STR, FMT, VARGS) trio_asprintf((STR), (FMT), (VARGS)) -#define strcasestr(H,N) strstr((H), (N)) -#endif - -#define dprintf(CTX, FMT...) if ((CTX)->caps & GLITE_LBU_DB_CAP_ERRORS) fprintf(stderr, ##FMT) - -struct glite_lbu_DBContext_s { - int backend; - struct { - int code; - char *desc; - } err; - int caps; -}; -typedef struct glite_lbu_DBContext_s glite_lbu_DBContext_t; - -struct glite_lbu_Statement_s { - glite_lbu_DBContext ctx; -}; -typedef struct glite_lbu_Statement_s glite_lbu_Statement_t; - - - -typedef struct { - int backend; - - int (*initContext)(glite_lbu_DBContext *ctx); - void (*freeContext)(glite_lbu_DBContext ctx); - int (*connect)(glite_lbu_DBContext ctx, const char *cs); - void (*close)(glite_lbu_DBContext ctx); - int (*queryCaps)(glite_lbu_DBContext ctx); - void (*setCaps)(glite_lbu_DBContext ctx, int caps); - - int (*transaction)(glite_lbu_DBContext ctx); - int (*commit)(glite_lbu_DBContext ctx); - int (*rollback)(glite_lbu_DBContext ctx); - - int (*fetchRow)(glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results); - void (*freeStmt)(glite_lbu_Statement *stmt); - - int (*queryIndices)(glite_lbu_DBContext ctx, const char *table, char ***key_names, char ****column_names); - int (*execSQL)(glite_lbu_DBContext ctx, const char *cmd, glite_lbu_Statement *stmt); - int (*queryColumns)(glite_lbu_Statement stmt_gen, char **cols); - - int (*prepareStmt)(glite_lbu_DBContext ctx, const char *sql, glite_lbu_Statement *stmt); - int (*execPreparedStmt_v)(glite_lbu_Statement stmt, int n, va_list ap); - long int (*lastid)(glite_lbu_Statement stmt); - - void (*timeToDB)(time_t, char **str); - void (*timestampToDB)(double t, char **str); - time_t (*DBToTime)(const char *str); - double (*DBToTimestamp)(const char *str); -} glite_lbu_DBBackend_t; - -int glite_lbu_DBSetError(glite_lbu_DBContext ctx, int code, const char *func, int line, const char *desc, ...); - -void glite_lbu_TimeToStrGeneric(time_t t, char **str, const char *amp); -void glite_lbu_TimestampToStrGeneric(double t, char **str, const char *amp); diff --git a/org.glite.lbjp-common.db/src/db-mysql.c b/org.glite.lbjp-common.db/src/db-mysql.c deleted file mode 100644 index 60468d7..0000000 --- a/org.glite.lbjp-common.db/src/db-mysql.c +++ /dev/null @@ -1,1121 +0,0 @@ -#include -#ifdef LBS_DB_PROFILE -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYSLOG_H -#include -#endif - -#ifdef WIN32 -#include -#ifndef STDCALL -#define STDCALL __stdcall -#endif -#else -#define STDCALL -#endif - -#include -#include -#include -#include - -#include "glite/lbu/trio.h" -#include "db.h" -#include "db-int.h" - - -#define GLITE_LBU_MYSQL_INDEX_VERSION 40001 -#define GLITE_LBU_MYSQL_PREPARED_VERSION 40102 -#define BUF_INSERT_ROW_ALLOC_BLOCK 1000 -#ifndef GLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH -#define GLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH 256 -#endif - -#define CLR_ERR(CTX) glite_lbu_DBClearError((glite_lbu_DBContext)(CTX)) -#define ERR(CTX, CODE, ARGS...) glite_lbu_DBSetError((glite_lbu_DBContext)((CTX)), (CODE), __FUNCTION__, __LINE__, ##ARGS) -#define STATUS(CTX) glite_lbu_DBError((glite_lbu_DBContext)((CTX)), NULL, NULL) -#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->generic.caps & GLITE_LBU_DB_CAP_TRANSACTIONS) != 0) -#define LOAD(SYM, SYM2) if ((*(void **)(&mysql_module.SYM) = dlsym(mysql_module.lib, SYM2)) == NULL) { \ - err = ERR(ctx, ENOENT, "can't load symbol '%s' from mysql library (%s)", SYM2, dlerror()); \ - break; \ -} - - - -struct glite_lbu_DBContextMysql_s { - struct glite_lbu_DBContext_s generic; - int in_transaction; /* this flag is set whenever we are in DB transaction */ - MYSQL *mysql; -}; -typedef struct glite_lbu_DBContextMysql_s *glite_lbu_DBContextMysql; - - -struct glite_lbu_StatementMysql_s { - glite_lbu_Statement_t generic; - - /* for simple commands */ - MYSQL_RES *result; - - /* for prepared commands */ - MYSQL_STMT *stmt; - unsigned long nrfields; - char *sql; -}; -typedef struct glite_lbu_StatementMysql_s *glite_lbu_StatementMysql; - - -/* - * mapping glite DB types to mysql types - */ -int glite_type_to_mysql[] = { - MYSQL_TYPE_NULL, - MYSQL_TYPE_TINY, - MYSQL_TYPE_LONG, - MYSQL_TYPE_TINY_BLOB, - MYSQL_TYPE_TINY_BLOB, - MYSQL_TYPE_BLOB, - MYSQL_TYPE_BLOB, - MYSQL_TYPE_MEDIUM_BLOB, - MYSQL_TYPE_MEDIUM_BLOB, - MYSQL_TYPE_LONG_BLOB, - MYSQL_TYPE_LONG_BLOB, - MYSQL_TYPE_VAR_STRING, - MYSQL_TYPE_STRING, - MYSQL_TYPE_DATE, - MYSQL_TYPE_TIME, - MYSQL_TYPE_DATETIME, - MYSQL_TYPE_TIMESTAMP, -}; - - -typedef struct { - void *lib; - pthread_mutex_t lock; - - void * STDCALL(*mysql_init)(void *); - unsigned long STDCALL(*mysql_get_client_version)(void); - int STDCALL(*mysql_options)(MYSQL *mysql, enum mysql_option option, const char *arg); - unsigned int STDCALL(*mysql_errno)(MYSQL *mysql); - const char *STDCALL(*mysql_error)(MYSQL *mysql); - unsigned int STDCALL(*mysql_stmt_errno)(MYSQL_STMT *stmt); - const char *STDCALL(*mysql_stmt_error)(MYSQL_STMT *stmt); - MYSQL * STDCALL(*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 STDCALL(*mysql_close)(MYSQL *mysql); - int STDCALL(*mysql_query)(MYSQL *mysql, const char *stmt_str); - MYSQL_RES *STDCALL(*mysql_store_result)(MYSQL *mysql); - void STDCALL(*mysql_free_result)(MYSQL_RES *result); - my_ulonglong STDCALL(*mysql_affected_rows)(MYSQL *mysql); - my_bool STDCALL(*mysql_stmt_close)(MYSQL_STMT *); - unsigned int STDCALL(*mysql_num_fields)(MYSQL_RES *result); - unsigned long *STDCALL(*mysql_fetch_lengths)(MYSQL_RES *result); - my_bool STDCALL(*mysql_stmt_bind_result)(MYSQL_STMT *stmt, MYSQL_BIND *bind); - int STDCALL(*mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *stmt_str, unsigned long length); - int STDCALL(*mysql_stmt_store_result)(MYSQL_STMT *stmt); - MYSQL_ROW STDCALL(*mysql_fetch_row)(MYSQL_RES *result); - MYSQL_FIELD *STDCALL(*mysql_fetch_field)(MYSQL_RES *result); - const char *STDCALL(*mysql_get_server_info)(MYSQL *mysql); - MYSQL_STMT *STDCALL(*mysql_stmt_init)(MYSQL *mysql); - my_bool STDCALL(*mysql_stmt_bind_param)(MYSQL_STMT *stmt, MYSQL_BIND *bind); - int STDCALL(*mysql_stmt_execute)(MYSQL_STMT *stmt); - int STDCALL(*mysql_stmt_fetch)(MYSQL_STMT *stmt); - my_ulonglong STDCALL(*mysql_stmt_insert_id)(MYSQL_STMT *stmt); - my_ulonglong STDCALL(*mysql_stmt_affected_rows)(MYSQL_STMT *stmt); - MYSQL_RES *STDCALL(*mysql_stmt_result_metadata)(MYSQL_STMT *stmt); - int STDCALL(*mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset); -} mysql_module_t; - - -/* backend module declaration */ -int glite_lbu_InitDBContextMysql(glite_lbu_DBContext *ctx_gen); -void glite_lbu_FreeDBContextMysql(glite_lbu_DBContext ctx_gen); -int glite_lbu_DBConnectMysql(glite_lbu_DBContext ctx_gen, const char *cs); -void glite_lbu_DBCloseMysql(glite_lbu_DBContext ctx_gen); -int glite_lbu_DBQueryCapsMysql(glite_lbu_DBContext ctx_gen); -void glite_lbu_DBSetCapsMysql(glite_lbu_DBContext commmon_ctx, int caps); -int glite_lbu_TransactionMysql(glite_lbu_DBContext ctx_gen); -int glite_lbu_CommitMysql(glite_lbu_DBContext ctx_gen); -int glite_lbu_RollbackMysql(glite_lbu_DBContext ctx_gen); -int glite_lbu_FetchRowMysql(glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results); -void glite_lbu_FreeStmtMysql(glite_lbu_Statement *stmt); -int glite_lbu_QueryIndicesMysql(glite_lbu_DBContext ctx_gen, const char *table, char ***key_names, char ****column_names); -int glite_lbu_ExecSQLMysql(glite_lbu_DBContext ctx_gen, const char *cmd, glite_lbu_Statement *stmt); -int glite_lbu_QueryColumnsMysql(glite_lbu_Statement stmt_gen, char **cols); -int glite_lbu_PrepareStmtMysql(glite_lbu_DBContext ctx_gen, const char *sql, glite_lbu_Statement *stmt_gen); -int glite_lbu_ExecPreparedStmtMysql_v(glite_lbu_Statement stmt_gen, int n, va_list ap); -long int glite_lbu_LastidMysql(glite_lbu_Statement stmt_gen); - -glite_lbu_DBBackend_t mysql_backend = { - backend: GLITE_LBU_DB_BACKEND_MYSQL, - - initContext: glite_lbu_InitDBContextMysql, - freeContext: glite_lbu_FreeDBContextMysql, - connect: glite_lbu_DBConnectMysql, - close: glite_lbu_DBCloseMysql, - queryCaps: glite_lbu_DBQueryCapsMysql, - setCaps: glite_lbu_DBSetCapsMysql, - transaction: glite_lbu_TransactionMysql, - commit: glite_lbu_CommitMysql, - rollback: glite_lbu_RollbackMysql, - fetchRow: glite_lbu_FetchRowMysql, - freeStmt: glite_lbu_FreeStmtMysql, - queryIndices: glite_lbu_QueryIndicesMysql, - execSQL: glite_lbu_ExecSQLMysql, - queryColumns: glite_lbu_QueryColumnsMysql, - - timeToDB: glite_lbu_TimeToStr, - timestampToDB: glite_lbu_TimestampToStr, - DBToTime: glite_lbu_StrToTime, - DBToTimestamp: glite_lbu_StrToTimestamp, - - prepareStmt: glite_lbu_PrepareStmtMysql, - execPreparedStmt_v: glite_lbu_ExecPreparedStmtMysql_v, - lastid: glite_lbu_LastidMysql, -}; - -static mysql_module_t mysql_module = { - lib: NULL, - lock: PTHREAD_MUTEX_INITIALIZER, -}; - - -static int myerr(glite_lbu_DBContextMysql ctx, const char *source, int line); -static int myerrstmt(glite_lbu_StatementMysql stmt, const char *source, int line); -static int myisokstmt(glite_lbu_StatementMysql stmt, const char *source, int line, int *retry); -static int db_connect(glite_lbu_DBContextMysql ctx, const char *cs, MYSQL **mysql); -static void db_close(MYSQL *mysql); -static int transaction_test(glite_lbu_DBContext ctx, int *caps); -static int FetchRowSimple(glite_lbu_DBContextMysql ctx, MYSQL_RES *result, unsigned long *lengths, char **results); -static int FetchRowPrepared(glite_lbu_DBContextMysql ctx, glite_lbu_StatementMysql stmt, unsigned int n, unsigned long *lengths, char **results); -static void set_time(MYSQL_TIME *mtime, const double time); -static void glite_lbu_DBCleanup(void); -static void glite_lbu_FreeStmt_int(glite_lbu_StatementMysql stmt); - - -/* ---- common ---- */ - - - -int glite_lbu_InitDBContextMysql(glite_lbu_DBContext *ctx_gen) { - glite_lbu_DBContextMysql ctx; - int err = 0; - int ver_u; - - ctx = calloc(1, sizeof *ctx); - if (!ctx) return ENOMEM; - *ctx_gen = (glite_lbu_DBContext)ctx; - - /* dynamic load the client library */ - pthread_mutex_lock(&mysql_module.lock); - if (!mysql_module.lib) { - mysql_module.lib = dlopen(MYSQL_SONAME, RTLD_LAZY | RTLD_LOCAL); - if (!mysql_module.lib) return ERR(ctx, ENOENT, "dlopen(): " MYSQL_SONAME ": %s", dlerror()); - do { - LOAD(mysql_init, "mysql_init"); - LOAD(mysql_get_client_version, "mysql_get_client_version"); - 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"); - - // check the runtime version - ver_u = mysql_module.mysql_get_client_version(); - if (ver_u != MYSQL_VERSION_ID) { - fprintf(stderr,"Warning: MySQL library version mismatch (compiled '%d', runtime '%d')", MYSQL_VERSION_ID, ver_u); -#ifdef SYSLOG_H - syslog(LOG_WARNING,"MySQL library version mismatch (compiled '%d', runtime '%d')", MYSQL_VERSION_ID, ver_u); -#endif - } - - pthread_mutex_unlock(&mysql_module.lock); - atexit(glite_lbu_DBCleanup); - } while(0); - - if (err) { - dlclose(mysql_module.lib); - mysql_module.lib = NULL; - pthread_mutex_unlock(&mysql_module.lock); - return err; - } - } else pthread_mutex_unlock(&mysql_module.lock); - - return 0; -} - - -void glite_lbu_FreeDBContextMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - if (ctx) { - assert(ctx->mysql == NULL); - free(ctx); - } -} - - -int glite_lbu_DBConnectMysql(glite_lbu_DBContext ctx_gen, const char *cs) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - if (db_connect(ctx, cs, &ctx->mysql) != 0 || - glite_lbu_ExecSQLMysql(ctx_gen, "SET AUTOCOMMIT=1", NULL) < 0 || - glite_lbu_ExecSQLMysql(ctx_gen, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ", NULL) < 0) - return STATUS(ctx); - else - return 0; -} - - -void glite_lbu_DBCloseMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - db_close(ctx->mysql); - ctx->mysql = NULL; - CLR_ERR(ctx); -} - - -int glite_lbu_DBQueryCapsMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - MYSQL *m = ctx->mysql; - int major,minor,sub,version,caps; - const char *ver_s; - - caps = 0; - - ver_s = mysql_module.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; - - if (version >= GLITE_LBU_MYSQL_INDEX_VERSION) caps |= GLITE_LBU_DB_CAP_INDEX; - if (version >= GLITE_LBU_MYSQL_PREPARED_VERSION) caps |= GLITE_LBU_DB_CAP_PREPARED; - - CLR_ERR(ctx); - transaction_test(ctx_gen, &caps); - - if (STATUS(ctx) == 0) return caps; - else return -1; -} - - -void glite_lbu_DBSetCapsMysql(glite_lbu_DBContext ctx_gen, int caps) { - ctx_gen->caps = caps; -} - - -int glite_lbu_TransactionMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - CLR_ERR(ctx); - if (USE_TRANS(ctx)) { - if (glite_lbu_ExecSQLMysql(ctx_gen, "SET AUTOCOMMIT=0", NULL) < 0) goto err; - if (glite_lbu_ExecSQLMysql(ctx_gen, "BEGIN", NULL) < 0) goto err; - ctx->in_transaction = 1; - } -err: - return STATUS(ctx); -} - - -int glite_lbu_CommitMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - CLR_ERR(ctx); - if (USE_TRANS(ctx)) { - if (glite_lbu_ExecSQLMysql(ctx_gen, "COMMIT", NULL) < 0) goto err; - if (glite_lbu_ExecSQLMysql(ctx_gen, "SET AUTOCOMMIT=1", NULL) < 0) goto err; - ctx->in_transaction = 0; - } -err: - return STATUS(ctx); -} - - -int glite_lbu_RollbackMysql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - - CLR_ERR(ctx); - if (USE_TRANS(ctx)) { - if (glite_lbu_ExecSQLMysql(ctx_gen, "ROLLBACK", NULL) < 0) goto err; - if (glite_lbu_ExecSQLMysql(ctx_gen, "SET AUTOCOMMIT=1", NULL) < 0) goto err; - ctx->in_transaction = 0; - } -err: - return STATUS(ctx); -} - - -int glite_lbu_FetchRowMysql(glite_lbu_Statement stmt_gen, unsigned int n, unsigned long *lengths, char **results) { - glite_lbu_StatementMysql stmt = (glite_lbu_StatementMysql)stmt_gen; - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)stmt->generic.ctx; - - memset(results, 0, n * sizeof(*results)); - if (stmt->result) return FetchRowSimple(ctx, stmt->result, lengths, results); - else return FetchRowPrepared(ctx, stmt, n, lengths, results); -} - - -static void glite_lbu_FreeStmt_int(glite_lbu_StatementMysql stmt) { - if (stmt) { - if (stmt->result) mysql_module.mysql_free_result(stmt->result); - if (stmt->stmt) mysql_module.mysql_stmt_close(stmt->stmt); - free(stmt->sql); - } -} - - -void glite_lbu_FreeStmtMysql(glite_lbu_Statement *stmt_gen) { - glite_lbu_StatementMysql *stmt = (glite_lbu_StatementMysql*)stmt_gen; - - glite_lbu_FreeStmt_int(*stmt); - free(*stmt); - *stmt = NULL; -} - - -int glite_lbu_QueryIndicesMysql(glite_lbu_DBContext ctx_gen, const char *table, char ***key_names, char ****column_names) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - glite_lbu_Statement stmt; - - size_t i,j,ret; - -/* XXX: "show index from" columns. Matches at least MySQL 4.0.11 */ - char *sql, *showcol[12]; - int Key_name,Seq_in_index,Column_name,Sub_part; - - char **keys = NULL; - size_t *cols = NULL; - char **col_names = NULL; - - size_t nkeys = 0; - - char ***idx = NULL; - - Key_name = Seq_in_index = Column_name = Sub_part = -1; - - asprintf(&sql, "show index from %s", table); - if (glite_lbu_ExecSQLMysql(ctx_gen,sql,&stmt)<0) { - free(sql); - return STATUS(ctx); - } - free(sql); - - while ((ret = glite_lbu_FetchRowMysql(stmt,sizeof(showcol)/sizeof(showcol[0]),NULL,showcol)) > 0) { - assert(ret <= (int)(sizeof showcol/sizeof showcol[0])); - - if (!col_names) { - col_names = malloc(ret * sizeof col_names[0]); - glite_lbu_QueryColumnsMysql(stmt,col_names); - for (i=0; i= 0 && Seq_in_index >= 0 && - Column_name >= 0 && Sub_part >= 0); - - } - - for (i=0; imysql, cmd)) { - /* error occured */ - switch (merr = mysql_module.mysql_errno(ctx->mysql)) { - case 0: - break; - case ER_DUP_ENTRY: - ERR(ctx, EEXIST, mysql_module.mysql_error(ctx->mysql)); - return -1; - break; - case CR_SERVER_LOST: - case CR_SERVER_GONE_ERROR: - if (ctx->in_transaction) { - ERR(ctx, ERESTART, mysql_module.mysql_error(ctx->mysql)); - return -1; - } - else if (retry_nr <= 0) - do_reconnect = 1; - break; - case ER_LOCK_DEADLOCK: - ERR(ctx, EDEADLOCK, mysql_module.mysql_error(ctx->mysql)); - return -1; - break; - default: - MY_ERR(ctx); - return -1; - break; - } - } - retry_nr++; - } - - if (stmt_gen) { - stmt = calloc(1, sizeof(*stmt)); - if (!stmt) { - ERR(ctx, ENOMEM, NULL); - return -1; - } - stmt->generic.ctx = ctx_gen; - stmt->result = mysql_module.mysql_store_result(ctx->mysql); - if (!stmt->result) { - if (mysql_module.mysql_errno(ctx->mysql)) { - MY_ERR(ctx); - free(stmt); - return -1; - } - } - *stmt_gen = (glite_lbu_Statement)stmt; - } else { - MYSQL_RES *r = mysql_module.mysql_store_result(ctx->mysql); - mysql_module.mysql_free_result(r); - } -#ifdef LBS_DB_PROFILE - pid = getpid(); - gettimeofday(&end,NULL); - end.tv_usec -= start.tv_usec; - end.tv_sec -= start.tv_sec; - if (end.tv_usec < 0) { end.tv_sec--; end.tv_usec += 1000000; } - - sum.tv_usec += end.tv_usec; - sum.tv_sec += end.tv_sec + sum.tv_usec / 1000000; - sum.tv_usec -= 1000000 * (sum.tv_usec / 1000000); - fprintf(stderr,"[%d] %s\n[%d] %3ld.%06ld (sum: %3ld.%06ld)\n",pid,cmd,pid,end.tv_sec,end.tv_usec,sum.tv_sec,sum.tv_usec); -#endif - - return mysql_module.mysql_affected_rows(ctx->mysql); -} - - -int glite_lbu_QueryColumnsMysql(glite_lbu_Statement stmt_gen, char **cols) -{ - glite_lbu_StatementMysql stmt = (glite_lbu_StatementMysql)stmt_gen; - int i = 0; - MYSQL_FIELD *f; - - CLR_ERR(stmt->generic.ctx); - if (!stmt->result) return ERR(stmt->generic.ctx, ENOTSUP, "QueryColumns implemented only for simple API"); - while ((f = mysql_module.mysql_fetch_field(stmt->result))) cols[i++] = f->name; - return i == 0; -} - - -/* ---- prepared --- */ - -int glite_lbu_PrepareStmtMysql(glite_lbu_DBContext ctx_gen, const char *sql, glite_lbu_Statement *stmt_gen) { - glite_lbu_DBContextMysql ctx = (glite_lbu_DBContextMysql)ctx_gen; - glite_lbu_StatementMysql stmt; - int ret, retry; - MYSQL_RES *meta; - - // init - stmt = calloc(1, sizeof(*stmt)); - stmt->generic.ctx = ctx_gen; - *stmt_gen = NULL; - - // create the SQL command - if ((stmt->stmt = mysql_module.mysql_stmt_init(ctx->mysql)) == NULL) - return STATUS(ctx); - - // prepare the SQL command - retry = 1; - do { - mysql_module.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_module.mysql_stmt_result_metadata(stmt->stmt)) != NULL) { - stmt->nrfields = mysql_module.mysql_num_fields(meta); - mysql_module.mysql_free_result(meta); - } else - stmt->nrfields = 0; - - // remember the command - stmt->sql = strdup(sql); - - *stmt_gen = (glite_lbu_Statement)stmt; - return CLR_ERR(ctx); - -failed: - glite_lbu_FreeStmt_int(stmt); - free(stmt); - return STATUS(ctx); -} - - -int glite_lbu_ExecPreparedStmtMysql_v(glite_lbu_Statement stmt_gen, int n, va_list ap) { - glite_lbu_StatementMysql stmt = (glite_lbu_StatementMysql)stmt_gen; - int i, prepare_retry; - glite_lbu_DBType type; - char *pchar; - int *pint; - long int *plint; - MYSQL_TIME *ptime; - int ret, retry; - MYSQL_BIND *binds = NULL; - void **data = NULL; - unsigned long *lens; - glite_lbu_Statement newstmt; - - // gather parameters - if (n) { - binds = calloc(n, sizeof(MYSQL_BIND)); - data = calloc(n, sizeof(void *)); - lens = calloc(n, sizeof(unsigned long *)); - } - for (i = 0; i < n; i++) { - type = va_arg(ap, glite_lbu_DBType); - switch (type) { - case GLITE_LBU_DB_TYPE_TINYINT: - pchar = binds[i].buffer = data[i] = malloc(sizeof(char)); - *pchar = va_arg(ap, int); - break; - - case GLITE_LBU_DB_TYPE_INT: - plint = binds[i].buffer = data[i] = malloc(sizeof(long int)); - *plint = va_arg(ap, long int); - break; - - case GLITE_LBU_DB_TYPE_BOOLEAN: - pint = binds[i].buffer = data[i] = malloc(sizeof(int)); - *pint = va_arg(ap, int) ? 1 : 0; - break; - - case GLITE_LBU_DB_TYPE_TINYBLOB: - case GLITE_LBU_DB_TYPE_TINYTEXT: - case GLITE_LBU_DB_TYPE_BLOB: - case GLITE_LBU_DB_TYPE_TEXT: - case GLITE_LBU_DB_TYPE_MEDIUMBLOB: - case GLITE_LBU_DB_TYPE_MEDIUMTEXT: - case GLITE_LBU_DB_TYPE_LONGBLOB: - case GLITE_LBU_DB_TYPE_LONGTEXT: - binds[i].buffer = va_arg(ap, void *); - binds[i].length = &lens[i]; - lens[i] = va_arg(ap, unsigned long); - break; - - case GLITE_LBU_DB_TYPE_VARCHAR: - case GLITE_LBU_DB_TYPE_CHAR: - binds[i].buffer = va_arg(ap, char *); - binds[i].length = &lens[i]; - lens[i] = binds[i].buffer ? strlen((char *)binds[i].buffer) : 0; - break; - - case GLITE_LBU_DB_TYPE_DATE: - case GLITE_LBU_DB_TYPE_TIME: - case GLITE_LBU_DB_TYPE_DATETIME: - ptime = binds[i].buffer = data[i] = malloc(sizeof(MYSQL_TIME)); - set_time(ptime, va_arg(ap, time_t)); - break; - - case GLITE_LBU_DB_TYPE_TIMESTAMP: - ptime = binds[i].buffer = data[i] = malloc(sizeof(MYSQL_TIME)); - set_time(ptime, va_arg(ap, double)); - break; - - case GLITE_LBU_DB_TYPE_NULL: - break; - - default: - assert("unimplemented parameter assign" == NULL); - break; - } - binds[i].buffer_type = glite_type_to_mysql[type]; - } - - prepare_retry = 2; - do { - // bind parameters - if (n) { - if (mysql_module.mysql_stmt_bind_param(stmt->stmt, binds) != 0) { - MY_ERRSTMT(stmt); - ret = -1; - goto statement_failed; - } - } - - // run - retry = 1; - do { - mysql_module.mysql_stmt_execute(stmt->stmt); - ret = MY_ISOKSTMT(stmt, &retry); - } while (ret == 0); - statement_failed: - if (ret == -1) { - if (mysql_module.mysql_stmt_errno(stmt->stmt) == ER_UNKNOWN_STMT_HANDLER) { - // expired the prepared command ==> restore it - if (glite_lbu_PrepareStmtMysql(stmt->generic.ctx, stmt->sql, &newstmt) == -1) goto failed; - glite_lbu_FreeStmt_int(stmt); - memcpy(stmt, newstmt, sizeof(struct glite_lbu_StatementMysql_s)); - prepare_retry--; - ret = 0; - } else goto failed; - } - } while (ret == 0 && prepare_retry > 0); - - // result - retry = 1; - do { - mysql_module.mysql_stmt_store_result(stmt->stmt); - ret = MY_ISOKSTMT(stmt, &retry); - } while (ret == 0); - if (ret == -1) goto failed; - - // free params - if (n) { - for (i = 0; i < n; i++) free(data[i]); - free(data); - free(binds); - free(lens); - } - CLR_ERR(stmt->generic.ctx); - return mysql_module.mysql_stmt_affected_rows(stmt->stmt); - -failed: - for (i = 0; i < n; i++) free(data[i]); - free(data); - free(binds); - free(lens); - return -1; -} - - -long int glite_lbu_LastidMysql(glite_lbu_Statement stmt_gen) { - glite_lbu_StatementMysql stmt = (glite_lbu_StatementMysql)stmt_gen; - my_ulonglong i; - - CLR_ERR(stmt_gen->ctx); - i = mysql_module.mysql_stmt_insert_id(stmt->stmt); - assert(i < ((unsigned long int)-1) >> 1); - return (long int)i; -} - - -/* - * helping function: find oud mysql error and sets on the context - */ -static int myerr(glite_lbu_DBContextMysql ctx, const char *source, int line) { - return glite_lbu_DBSetError(&ctx->generic, EIO, source, line, mysql_module.mysql_error(ctx->mysql)); -} - - -/* - * helping function: find oud mysql stmt error and sets on the context - */ -static int myerrstmt(glite_lbu_StatementMysql stmt, const char *source, int line) { - return glite_lbu_DBSetError(stmt->generic.ctx, EIO, source, line, mysql_module.mysql_stmt_error(stmt->stmt)); -} - - -/* - * helping function: error handle - * - * \return -1 failed - * \return 0 retry - * \return 1 OK - */ -static int myisokstmt(glite_lbu_StatementMysql stmt, const char *source, int line, int *retry) { - switch (mysql_module.mysql_stmt_errno(stmt->stmt)) { - case 0: - return 1; - break; - case ER_DUP_ENTRY: - glite_lbu_DBSetError(stmt->generic.ctx, EEXIST, source, line, mysql_module.mysql_stmt_error(stmt->stmt)); - return -1; - break; - case CR_SERVER_LOST: - case CR_SERVER_GONE_ERROR: - if (*retry > 0) { - (*retry)--; - return 0; - } else { - myerrstmt(stmt, source, line); - return -1; - } - break; - default: - myerrstmt(stmt, source, line); - return -1; - break; - } -} - - -/* - * mysql connect - */ -static int db_connect(glite_lbu_DBContextMysql ctx, const char *cs, MYSQL **mysql) { - char *buf = NULL; - char *host,*user,*pw,*db; - char *slash,*at,*colon; - int ret; -#if MYSQL_VERSION_ID >= 50013 - my_bool reconnect = 1; -#endif - - // needed for SQL result parameters - assert(sizeof(int) >= sizeof(my_bool)); - - if (!cs) return ERR(ctx, EINVAL, "connect string not specified"); - - if (!(*mysql = mysql_module.mysql_init(NULL))) return ERR(ctx, ENOMEM, NULL); - - mysql_module.mysql_options(*mysql, MYSQL_READ_DEFAULT_FILE, "my"); -#if MYSQL_VERSION_ID >= 50013 - /* XXX: may result in weird behaviour in the middle of transaction */ - mysql_module.mysql_options(*mysql, MYSQL_OPT_RECONNECT, &reconnect); -#endif - - host = user = pw = db = NULL; - - buf = strdup(cs); - slash = strchr(buf,'/'); - at = strrchr(buf,'@'); - colon = strrchr(buf,':'); - - if (!slash || !at || !colon) { - free(buf); - db_close(*mysql); - *mysql = NULL; - return ERR(ctx, EINVAL, "Invalid DB connect string"); - } - - *slash = *at = *colon = 0; - host = at+1; - user = buf; - pw = slash+1; - db = colon+1; - - /* ljocha: CLIENT_FOUND_ROWS added to make authorization check - * working in update_notif(). - * Hope it does not break anything else */ - if (!mysql_module.mysql_real_connect(*mysql,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) { - ret = MY_ERR(ctx); - db_close(*mysql); - *mysql = NULL; - free(buf); - return ret; - } - free(buf); - - return CLR_ERR(ctx); -} - - -/* - * mysql close - */ -static void db_close(MYSQL *mysql) { - if (mysql) mysql_module.mysql_close(mysql); -} - - -/* - * test transactions capability: - */ -static int transaction_test(glite_lbu_DBContext ctx, int *caps) { - glite_lbu_Statement stmt; - char *table[1] = { NULL }, *res[2] = { NULL, NULL }, *cmd = NULL; - int retval; - - (*caps) &= ~GLITE_LBU_DB_CAP_TRANSACTIONS; - - if ((retval = glite_lbu_ExecSQLMysql(ctx, "SHOW TABLES", &stmt)) <= 0 || glite_lbu_FetchRowMysql(stmt, 1, NULL, table) < 0) goto quit; - glite_lbu_FreeStmtMysql(&stmt); - - trio_asprintf(&cmd, "SHOW CREATE TABLE %|Ss", table[0]); - if (glite_lbu_ExecSQLMysql(ctx, cmd, &stmt) <= 0 || (retval = glite_lbu_FetchRowMysql(stmt, 2, NULL, res)) < 0 ) goto quit; - if (retval != 2 || strcmp(res[0], table[0])) { - ERR(ctx, EIO, "unexpected show create result"); - goto quit; - } - - if (strstr(res[1],"ENGINE=InnoDB")) - (*caps) |= GLITE_LBU_DB_CAP_TRANSACTIONS; - -#ifdef LBS_DB_PROFILE - fprintf(stderr, "[%d] use_transactions = %d\n", getpid(), USE_TRANS(ctx)); -#endif - -quit: - glite_lbu_FreeStmtMysql(&stmt); - free(table[0]); - free(res[0]); - free(res[1]); - free(cmd); - return STATUS(ctx); -} - - -/* - * simple version of the fetch - */ -static int FetchRowSimple(glite_lbu_DBContextMysql ctx, MYSQL_RES *result, unsigned long *lengths, char **results) { - MYSQL_ROW row; - unsigned int nr, i; - unsigned long *len; - - CLR_ERR(ctx); - - if (!(row = mysql_module.mysql_fetch_row(result))) { - if (mysql_module.mysql_errno((MYSQL *) ctx->mysql)) { - MY_ERR(ctx); - return -1; - } else return 0; - } - - nr = mysql_module.mysql_num_fields(result); - len = mysql_module.mysql_fetch_lengths(result); - for (i=0; inrfields) { - ERR(ctx, EINVAL, "bad number of result fields"); - return -1; - } - - // space for results - if (n) binds = calloc(n, sizeof(MYSQL_BIND)); - if (!lengths) { - lens = calloc(n, sizeof(unsigned long)); - lengths = lens; - } - for (i = 0; i < n; i++) { - binds[i].buffer_type = MYSQL_TYPE_VAR_STRING; - binds[i].buffer_length = GLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH - 1; - binds[i].length = &lengths[i]; - binds[i].buffer = results[i] = calloc(1, GLITE_LBU_DEFAULT_RESULT_BUFFER_LENGTH); - } - if (mysql_module.mysql_stmt_bind_result(stmt->stmt, binds) != 0) goto failedstmt; - - // fetch data, all can be truncated - retry = 1; - do { - switch(mysql_module.mysql_stmt_fetch(stmt->stmt)) { -#ifdef MYSQL_DATA_TRUNCATED - case MYSQL_DATA_TRUNCATED: -#endif - case 0: - ret = 1; break; - case 1: ret = MY_ISOKSTMT(stmt, &retry); break; - case MYSQL_NO_DATA: ret = 0; goto quit; /* it's OK */ - default: ERR(ctx, EIO, "other fetch error"); goto failed; - } - } while (ret == 0); - if (ret == -1) goto failed; - - // check if all fileds had enough buffer space - for (i = 0; i < n; i++) { - // fetch the rest if needed - if (lengths[i] > binds[i].buffer_length) { - unsigned int fetched; - - fetched = binds[i].buffer_length; - if ((results[i] = realloc(results[i], lengths[i] + 1)) == NULL) { - ERR(ctx, ENOMEM, "insufficient memory for field data"); - goto failed; - } - results[i][lengths[i]] = '\000'; - binds[i].buffer = results[i] + fetched; - binds[i].buffer_length = lengths[i] - fetched; - - retry = 1; - do { - switch (mysql_module.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 */ - default: ERR(ctx, EIO, "other fetch error"); goto failed; - } - } while (ret == 0); - if (ret == -1) goto failed; - } - } - - CLR_ERR(ctx); - free(binds); - free(lens); - return n; - -failedstmt: - MY_ERRSTMT(stmt); -failed: - ret = -1; -quit: - free(binds); - free(lens); - for (i = 0; i < n; i++) { - free(results[i]); - results[i] = NULL; - } - return ret; -} - - -static void set_time(MYSQL_TIME *mtime, const double time) { - struct tm tm; - time_t itime; - - itime = time; - gmtime_r(&itime, &tm); - memset(mtime, 0, sizeof *mtime); - mtime->year = tm.tm_year + 1900; - mtime->month = tm.tm_mon + 1; - mtime->day = tm.tm_mday; - mtime->hour = tm.tm_hour; - mtime->minute = tm.tm_min; - mtime->second = tm.tm_sec; - mtime->second_part = (time - itime) * 1000; -} - - -static void glite_lbu_DBCleanup(void) { - pthread_mutex_lock(&mysql_module.lock); - if (mysql_module.lib) { - dlclose(mysql_module.lib); - mysql_module.lib = NULL; - } - pthread_mutex_unlock(&mysql_module.lock); -} - - diff --git a/org.glite.lbjp-common.db/src/db-pg.c b/org.glite.lbjp-common.db/src/db-pg.c deleted file mode 100644 index 7d8d743..0000000 --- a/org.glite.lbjp-common.db/src/db-pg.c +++ /dev/null @@ -1,603 +0,0 @@ -/** - * Simple postgres module with org.glite.lbjp-common.db interface. - * - * PostgreSQL limitations: - * - prepared commands requires server >= 8.2 - * - binary data need to be handled manually (libpq limitation) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "glite/lbu/trio.h" -#include "db.h" -#include "db-int.h" - -#ifdef WIN32 -#define STDCALL __stdcall -#else -#define STDCALL -#endif - -#define DB_CONNECT_TIMEOUT "20" - -#ifdef LOG - #define lprintf(FMT...) fprintf(stdout, "[db-pg] %s: ", __FUNCTION__); fprintf(stdout, ##FMT); -#else - #define lprintf(FMT...) -#endif - -#define set_error(CTX, CODE, DESC...) glite_lbu_DBSetError((glite_lbu_DBContext)(CTX), (CODE), __FUNCTION__, __LINE__, ##DESC) - -#define LOAD(SYM, SYM2) if ((*(void **)(&psql_module.SYM) = dlsym(psql_module.lib, SYM2)) == NULL) { \ - err = set_error(ctx, ENOENT, "can't load symbol '%s' from psql library (%s)", SYM2, dlerror()); \ - break; \ -} - - -struct glite_lbu_DBContextPsql_s { - struct glite_lbu_DBContext_s generic; - PGconn *conn; - int prepared_counts[4]; -}; -typedef struct glite_lbu_DBContextPsql_s *glite_lbu_DBContextPsql; - -struct glite_lbu_StatementPsql_s { - glite_lbu_Statement_t generic; - PGresult *res; - int row, nrows; - char *sql, *name; -}; -typedef struct glite_lbu_StatementPsql_s *glite_lbu_StatementPsql; - -typedef struct { - void *lib; - pthread_mutex_t lock; - - /* functions from 8.3.8 client library version (libpq-fe.h) */ - PGconn *STDCALL(*PQconnectdb)(const char *conninfo); - ConnStatusType STDCALL(*PQstatus)(const PGconn *conn); - void STDCALL(*PQfinish)(PGconn *conn); - char *STDCALL(*PQerrorMessage)(const PGconn *conn); - int STDCALL(*PQnfields)(const PGresult *res); - char *STDCALL(*PQgetvalue)(const PGresult *res, int tup_num, int field_num); - int STDCALL(*PQgetlength)(const PGresult *res, int tup_num, int field_num); - void STDCALL(*PQclear)(PGresult *res); - PGresult *STDCALL(*PQexec)(PGconn *conn, const char *query); - ExecStatusType STDCALL(*PQresultStatus)(const PGresult *res); - char *STDCALL(*PQresultErrorMessage)(const PGresult *res); - char *STDCALL(*PQcmdTuples)(PGresult *res); - int STDCALL(*PQntuples)(const PGresult *res); - char *STDCALL(*PQfname)(const PGresult *res, int field_num); - size_t STDCALL(*PQescapeStringConn)(PGconn *conn, - char *to, const char *from, size_t length, - int *error); - void STDCALL(*PQfreemem)(void *ptr); -} psql_module_t; - - -static void glite_lbu_DBCleanup(void); - -/* backend module declaration */ -int glite_lbu_InitDBContextPsql(glite_lbu_DBContext *ctx_gen); -void glite_lbu_FreeDBContextPsql(glite_lbu_DBContext ctx_gen); -int glite_lbu_DBConnectPsql(glite_lbu_DBContext ctx_gen, const char *cs); -void glite_lbu_DBClosePsql(glite_lbu_DBContext ctx_gen); -int glite_lbu_DBQueryCapsPsql(glite_lbu_DBContext ctx_gen); -void glite_lbu_DBSetCapsPsql(glite_lbu_DBContext commmon_ctx, int caps); -int glite_lbu_TransactionPsql(glite_lbu_DBContext ctx_gen); -int glite_lbu_CommitPsql(glite_lbu_DBContext ctx_gen); -int glite_lbu_RollbackPsql(glite_lbu_DBContext ctx_gen); -int glite_lbu_FetchRowPsql(glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results); -void glite_lbu_FreeStmtPsql(glite_lbu_Statement *stmt); -//int glite_lbu_QueryIndicesPsql(glite_lbu_DBContext ctx_gen, const char *table, char ***key_names, char ****column_names); -int glite_lbu_ExecSQLPsql(glite_lbu_DBContext ctx_gen, const char *cmd, glite_lbu_Statement *stmt); -int glite_lbu_QueryColumnsPsql(glite_lbu_Statement stmt_gen, char **cols); -int glite_lbu_PrepareStmtPsql(glite_lbu_DBContext ctx_gen, const char *sql, glite_lbu_Statement *stmt_gen); -int glite_lbu_ExecPreparedStmtPsql_v(glite_lbu_Statement stmt_gen, int n, va_list ap); -//long int glite_lbu_LastidPsql(glite_lbu_Statement stmt_gen); - -glite_lbu_DBBackend_t psql_backend = { - backend: GLITE_LBU_DB_BACKEND_PSQL, - - initContext: glite_lbu_InitDBContextPsql, - freeContext: glite_lbu_FreeDBContextPsql, - connect: glite_lbu_DBConnectPsql, - close: glite_lbu_DBClosePsql, - queryCaps: glite_lbu_DBQueryCapsPsql, - setCaps: glite_lbu_DBSetCapsPsql, - transaction: glite_lbu_TransactionPsql, - commit: glite_lbu_CommitPsql, - rollback: glite_lbu_RollbackPsql, - fetchRow: glite_lbu_FetchRowPsql, - freeStmt: glite_lbu_FreeStmtPsql, - queryIndices: NULL /*glite_lbu_QueryIndicesPsql*/, - execSQL: glite_lbu_ExecSQLPsql, - queryColumns: glite_lbu_QueryColumnsPsql, - - timeToDB: glite_lbu_TimeToStr, - timestampToDB: glite_lbu_TimestampToStr, - DBToTime: glite_lbu_StrToTime, - DBToTimestamp: glite_lbu_StrToTimestamp, - - prepareStmt: glite_lbu_PrepareStmtPsql, - execPreparedStmt_v: glite_lbu_ExecPreparedStmtPsql_v, - lastid: NULL/*glite_lbu_LastidPsql*/, -}; - -static psql_module_t psql_module = { - lib: NULL, - lock: PTHREAD_MUTEX_INITIALIZER, -}; - - -/* nicer identifiers in PREPARE/EXECUTE commands */ -static const char *prepared_names[4] = {"select", "update", "insert", "other"}; - - -int glite_lbu_InitDBContextPsql(glite_lbu_DBContext *ctx_gen) { - glite_lbu_DBContextPsql ctx; - int err = 0; - - ctx = calloc(1, sizeof *ctx); - if (!ctx) return ENOMEM; - *ctx_gen = (glite_lbu_DBContext)ctx; - - /* dynamic load of the client library */ - pthread_mutex_lock(&psql_module.lock); - if (!psql_module.lib) { - psql_module.lib = dlopen(PSQL_SONAME, RTLD_LAZY | RTLD_LOCAL); - if (!psql_module.lib) return set_error(ctx, ENOENT, "dlopen(): " PSQL_SONAME ": %s", dlerror()); - do { - LOAD(PQconnectdb, "PQconnectdb"); - LOAD(PQstatus, "PQstatus"); - LOAD(PQfinish, "PQfinish"); - LOAD(PQerrorMessage, "PQerrorMessage"); - LOAD(PQnfields, "PQnfields"); - LOAD(PQgetvalue, "PQgetvalue"); - LOAD(PQgetlength, "PQgetlength"); - LOAD(PQclear, "PQclear"); - LOAD(PQexec, "PQexec"); - LOAD(PQresultStatus, "PQresultStatus"); - LOAD(PQresultErrorMessage, "PQresultErrorMessage"); - LOAD(PQcmdTuples, "PQcmdTuples"); - LOAD(PQntuples, "PQntuples"); - LOAD(PQfname, "PQfname"); - LOAD(PQescapeStringConn, "PQescapeStringConn"); - LOAD(PQfreemem, "PQfreemem"); - - pthread_mutex_unlock(&psql_module.lock); - atexit(glite_lbu_DBCleanup); - } while(0); - - if (err) { - dlclose(psql_module.lib); - psql_module.lib = NULL; - pthread_mutex_unlock(&psql_module.lock); - return err; - } - } else pthread_mutex_unlock(&psql_module.lock); - - return 0; -} - - -void glite_lbu_FreeDBContextPsql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - - if (ctx) { - assert(ctx->conn == NULL); - free(ctx); - } -} - - -int glite_lbu_DBConnectPsql(glite_lbu_DBContext ctx_gen, const char *cs) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - char *buf, *slash, *at, *colon, *host, *user, *pw, *db, *pgcsbuf, *pgcs; - char *err; - - host = user = pw = db = NULL; - buf = strdup(cs); - slash = strchr(buf,'/'); - at = strrchr(buf,'@'); - colon = strrchr(buf,':'); - if (!slash || !at || !colon) { - free(buf); - return set_error(ctx, EINVAL, "Invalid DB connect string"); - } - *slash = *at = *colon = 0; - host = at+1; - user = buf; - pw = slash+1; - db = colon+1; - - trio_asprintf(&pgcsbuf, "host='%|Ss' dbname='%|Ss' user='%|Ss' password='%|Ss' connect_timeout=" DB_CONNECT_TIMEOUT, host, db, user, pw); - /* simulate socket acces via localhost similar to MySQL */ - if (strcmp(host, "localhost") == 0) pgcs = pgcsbuf + strlen("host='localhost' "); - else pgcs = pgcsbuf; - free(buf); - - lprintf("connection string = %s\n", pgcs); - ctx->conn = psql_module.PQconnectdb(pgcs); - free(pgcsbuf); - if (!ctx->conn) return ENOMEM; - - - - if (psql_module.PQstatus(ctx->conn) != CONNECTION_OK) { - asprintf(&err, "Can't connect, %s", psql_module.PQerrorMessage(ctx->conn)); - psql_module.PQfinish(ctx->conn); - ctx->conn = NULL; - set_error(ctx, EIO, err); - free(err); - return EIO; - } - - return 0; -} - - -void glite_lbu_DBClosePsql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - - if (ctx->conn) { - psql_module.PQfinish(ctx->conn); - ctx->conn = NULL; - } -} - - -int glite_lbu_DBQueryCapsPsql(glite_lbu_DBContext ctx_gen) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - glite_lbu_Statement stmt; - int major, minor, sub, version; - int has_prepared = 0; - char *res = NULL; - - if (glite_lbu_ExecSQLPsql(ctx_gen, "SHOW server_version", &stmt) == -1) return -1; - switch (glite_lbu_FetchRowPsql(stmt, 1, NULL, &res)) { - case 1: - break; - case -1: - has_prepared = -1; - goto quit; - default: - goto quit; - } - if (sscanf(res, "%d.%d.%d", &major, &minor, &sub) != 3) { - set_error(ctx, EIO, "can't parse PostgreSQL version string"); - goto quit; - } - version = 10000*major + 100*minor + sub; - has_prepared = version >= 80200 ? GLITE_LBU_DB_CAP_PREPARED : 0; - -quit: - free(res); - glite_lbu_FreeStmtPsql(&stmt); - return has_prepared; -} - - -void glite_lbu_DBSetCapsPsql(glite_lbu_DBContext ctx_gen, int caps) { - ctx_gen->caps = caps; -} - - -int glite_lbu_TransactionPsql(glite_lbu_DBContext ctx_gen __attribute((unused))) { - return 0; -} - - -int glite_lbu_CommitPsql(glite_lbu_DBContext ctx_gen __attribute((unused))) { - return 0; -} - - -int glite_lbu_RollbackPsql(glite_lbu_DBContext ctx_gen __attribute((unused))) { - return 0; -} - - -int glite_lbu_FetchRowPsql(glite_lbu_Statement stmt_gen, unsigned int maxn, unsigned long *lengths, char **results) { - glite_lbu_StatementPsql stmt = (glite_lbu_StatementPsql)stmt_gen; - unsigned int i, n; - char *s; - - if (stmt->row >= stmt->nrows) return 0; - - n = psql_module.PQnfields(stmt->res); - if (n <= 0) { - set_error(stmt->generic.ctx, EINVAL, "Result set w/o columns"); - return -1; - } - if (n > maxn) { - set_error(stmt->generic.ctx, EINVAL, "Not enough room for the result"); - return -1; - } - for (i = 0; i < n; i++) { - /* sanity check for internal error (NULL when invalid row) */ - s = psql_module.PQgetvalue(stmt->res, stmt->row, i) ? : ""; - results[i] = strdup(s); - if (lengths) lengths[i] = strlen(s); - } - - stmt->row++; - return n; -} - - -void glite_lbu_FreeStmtPsql(glite_lbu_Statement *stmt_gen) { - glite_lbu_DBContextPsql ctx; - glite_lbu_StatementPsql stmt; - char *sql; - - if (!*stmt_gen) return; - stmt = (glite_lbu_StatementPsql)(*stmt_gen); - ctx = (glite_lbu_DBContextPsql)stmt->generic.ctx; - if (stmt->res) psql_module.PQclear(stmt->res); - if (stmt->name) { - asprintf(&sql, "DEALLOCATE %s", stmt->name); - stmt->res = psql_module.PQexec(ctx->conn, sql); - free(sql); - psql_module.PQclear(stmt->res); - } - free(stmt->name); - free(stmt->sql); - free(stmt); - *stmt_gen = NULL; -} - - -int glite_lbu_ExecSQLPsql(glite_lbu_DBContext ctx_gen, const char *cmd, glite_lbu_Statement *stmt_out) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - glite_lbu_StatementPsql stmt = NULL; - int status, n; - char *nstr, *errmsg, *pos; - PGresult *res; - - lprintf("command = %s\n", cmd); - if (stmt_out) *stmt_out = NULL; - if ((res = psql_module.PQexec(ctx->conn, cmd)) == NULL) { - ctx->generic.err.code = ENOMEM; - return -1; - } - - status = psql_module.PQresultStatus(res); - if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { - errmsg = psql_module.PQresultErrorMessage(res); - if (errmsg) { - errmsg = strdup(errmsg); - if ((pos = strrchr(errmsg, '\n')) != NULL) pos[0] = '\0'; - } - set_error(ctx, EIO, errmsg); - free(errmsg); - psql_module.PQclear(res); - return -1; - } - - nstr = psql_module.PQcmdTuples(res); - if (nstr && nstr[0]) n = atoi(nstr); - else n = psql_module.PQntuples(res); - if (stmt_out) { - stmt = calloc(1, sizeof(*stmt)); - stmt->generic.ctx = ctx_gen; - stmt->res = res; - stmt->nrows = n; - *stmt_out = (glite_lbu_Statement)stmt; - } else { - psql_module.PQclear(res); - } - return n; -} - - -int glite_lbu_QueryColumnsPsql(glite_lbu_Statement stmt_gen, char **cols) { - glite_lbu_StatementPsql stmt = (glite_lbu_StatementPsql)stmt_gen; - int n, i; - - n = psql_module.PQnfields(stmt->res); - for (i = 0; i < n; i++) { - cols[i] = psql_module.PQfname(stmt->res, i); - } - return -1; -} - - -int glite_lbu_PrepareStmtPsql(glite_lbu_DBContext ctx_gen, const char *sql, glite_lbu_Statement *stmt_out) { - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)ctx_gen; - int i, retval = -1; - const char *selectp, *updatep, *insertp, *minp; - char *sqlPrep = NULL, *s = NULL; - glite_lbu_StatementPsql stmt; - PGresult *res = NULL; - - // init - stmt = calloc(1, sizeof(*stmt)); - stmt->generic.ctx = ctx_gen; - stmt->sql = strdup(sql); - - // name of the prepared command used as ID in postgres - i = -1; - minp = stmt->sql + strlen(stmt->sql); - selectp = strcasestr(stmt->sql, "SELECT"); - updatep = strcasestr(stmt->sql, "UPDATE"); - insertp = strcasestr(stmt->sql, "INSERT"); - if (selectp && selectp < minp) { minp = selectp; i = 0; } - if (updatep && updatep < minp) { minp = updatep; i = 1; } - if (insertp && insertp < minp) { minp = insertp; i = 2; } - if (i == -1 || minp[0] == '\0') i = 3; - asprintf(&stmt->name, "%s%d", prepared_names[i], ++ctx->prepared_counts[i]); - - asprintf(&sqlPrep, "PREPARE %s AS %s", stmt->name, stmt->sql); - lprintf("prepare = %s\n", sqlPrep); - res = psql_module.PQexec(ctx->conn, sqlPrep); - if (psql_module.PQresultStatus(res) != PGRES_COMMAND_OK) { - asprintf(&s, "error preparing command: %s", psql_module.PQerrorMessage(ctx->conn)); - set_error(ctx, EIO, s); - free(s); s = NULL; - goto quit; - } - - *stmt_out = (glite_lbu_Statement)stmt; - retval = 0; - -quit: - free(sqlPrep); - if (res) psql_module.PQclear(res); - if (!retval) return 0; - - free(stmt->name); - free(stmt->sql); - free(stmt); - return retval; -} - - -int glite_lbu_ExecPreparedStmtPsql_v(glite_lbu_Statement stmt_gen, int n, va_list ap) { - glite_lbu_StatementPsql stmt = (glite_lbu_StatementPsql)stmt_gen; - glite_lbu_DBContextPsql ctx = (glite_lbu_DBContextPsql)stmt_gen->ctx; - int i, retval = -1, status; - char **tmpdata = NULL; - char *sql = NULL, *s, *nstr; - size_t data_len = 0; - - glite_lbu_DBType type; - - if (!stmt || !stmt->sql || !stmt->name) - return set_error(ctx, EINVAL, "PrepareStmt() not called"); - - if (stmt->res) { - psql_module.PQclear(stmt->res); - stmt->res = NULL; - } - - // gather parameters - if (n) { - tmpdata = calloc(n, sizeof(char *)); - } - for (i = 0; i < n; i++) { - type = va_arg(ap, glite_lbu_DBType); - - switch(type) { - case GLITE_LBU_DB_TYPE_TINYINT: - asprintf(&tmpdata[i], "%d", va_arg(ap, int)); - break; - - case GLITE_LBU_DB_TYPE_INT: - asprintf(&tmpdata[i], "%ld", va_arg(ap, long int)); - break; - - case GLITE_LBU_DB_TYPE_TINYBLOB: - case GLITE_LBU_DB_TYPE_TINYTEXT: - case GLITE_LBU_DB_TYPE_BLOB: - case GLITE_LBU_DB_TYPE_TEXT: - case GLITE_LBU_DB_TYPE_MEDIUMBLOB: - case GLITE_LBU_DB_TYPE_MEDIUMTEXT: - case GLITE_LBU_DB_TYPE_LONGBLOB: - case GLITE_LBU_DB_TYPE_LONGTEXT: { - char *tmp, *s; - unsigned long binary_len; - - s = va_arg(ap, char *); - binary_len = va_arg(ap, unsigned long); - lprintf("blob, len = %lu, ptr = %p\n", binary_len, s); - if (s) { - tmp = malloc(2*binary_len + 1); - psql_module.PQescapeStringConn(ctx->conn, tmp, s, binary_len, NULL); - asprintf(&tmpdata[i], "'%s'", tmp); - lprintf("escaped: '%s'\n", tmpdata[i]); - free(tmp); - } else - tmpdata[i] = strdup("NULL"); - break; - } - - - case GLITE_LBU_DB_TYPE_VARCHAR: - case GLITE_LBU_DB_TYPE_CHAR: - s = va_arg(ap, char *); - if (s) trio_asprintf(&tmpdata[i], "'%|Ss'", s); - else tmpdata[i] = strdup("NULL"); - break; - - case GLITE_LBU_DB_TYPE_DATE: - case GLITE_LBU_DB_TYPE_TIME: - case GLITE_LBU_DB_TYPE_DATETIME: - glite_lbu_TimeToStr(va_arg(ap, time_t), &tmpdata[i]); - break; - - case GLITE_LBU_DB_TYPE_TIMESTAMP: - glite_lbu_TimestampToStr(va_arg(ap, double), &tmpdata[i]); - break; - - case GLITE_LBU_DB_TYPE_NULL: - tmpdata[i] = strdup("NULL"); - break; - - case GLITE_LBU_DB_TYPE_BOOLEAN: - tmpdata[i] = strdup(va_arg(ap, int) ? "true" : "false"); - break; - - default: - lprintf("unknown type %d\n", type); - set_error(ctx, EINVAL, "unimplemented type"); - goto quit; - } - - data_len += strlen(tmpdata[i]); - } - - asprintf(&sql, "EXECUTE %s", stmt->name); - s = realloc(sql, strlen(sql) + (2 * n - 2) + strlen(" ()") + data_len + 1); - if (!s) goto quit; - sql = s; - for (i = 0; i < n; i++) { - strcat(sql, i ? ", " : " (" ); s += 2; - strcat(sql, tmpdata[i]); - } - if (n) strcat(sql, ")"); - - lprintf("exec prepared: n = %d, sql = '%s'\n", n, sql); - stmt->res = psql_module.PQexec(ctx->conn, sql); - status = psql_module.PQresultStatus(stmt->res); - if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { - asprintf(&s, "error executing prepared command '%s' parameters '%s': %s", stmt->sql, sql, psql_module.PQerrorMessage(ctx->conn)); - set_error(ctx, EIO, s); - free(s); s = NULL; - goto quit; - } - nstr = psql_module.PQcmdTuples(stmt->res); - //lprintf("cmdtuples: '%s'\n", nstr); - if (nstr && nstr[0]) retval = atoi(nstr); - else retval = psql_module.PQntuples(stmt->res); - stmt->nrows = retval; - stmt->row = 0; - //lprintf("ntuples/retval: %d\n", retval); - -quit: - for (i = 0; i < n; i++) free(tmpdata[i]); - free(tmpdata); - free(sql); - return retval; -} - - -static void glite_lbu_DBCleanup(void) { - pthread_mutex_lock(&psql_module.lock); - if (psql_module.lib) { - dlclose(psql_module.lib); - psql_module.lib = NULL; - } - pthread_mutex_unlock(&psql_module.lock); -} diff --git a/org.glite.lbjp-common.db/src/db.c b/org.glite.lbjp-common.db/src/db.c deleted file mode 100644 index d65d5a8..0000000 --- a/org.glite.lbjp-common.db/src/db.c +++ /dev/null @@ -1,396 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "db.h" -#include "db-int.h" - - -#define VALID(BACKEND) ((BACKEND) >= 0 && (BACKEND) < GLITE_LBU_DB_BACKEND_LAST) - - -struct glite_lbu_bufInsert_s { - glite_lbu_DBContext ctx; - char *table_name; - char *columns; /* names of columns to be inserted into - * (values separated with commas) */ - char **rows; /* each row hold string of one row to be inserted - * (values separated with commas) */ - long rec_num, /* actual number of rows in structure */ - rec_size; /* approx. size of a real insert string */ - long size_limit, /* size and # of records limit which trigger */ - record_limit; /* real insert; zero means unlimitted */ -}; - - -/* possible backends */ -#ifdef MYSQL_SONAME -extern glite_lbu_DBBackend_t mysql_backend; -#else -#define mysql_backend no_backend -#endif -#ifdef PSQL_SONAME -extern glite_lbu_DBBackend_t psql_backend; -#else -#define psql_backend no_backend -#endif - -glite_lbu_DBBackend_t no_backend = { - backend: -1, - - /* functions unspecified */ -}; - -glite_lbu_DBBackend_t *backends[GLITE_LBU_DB_BACKEND_LAST] = { - &mysql_backend, - &psql_backend -}; - - -/* --- internal functions ---- */ - -int glite_lbu_DBClearError(glite_lbu_DBContext ctx) { - ctx->err.code = 0; - if (ctx->err.desc) { - free(ctx->err.desc); - ctx->err.desc = NULL; - } - return 0; -} - - -int glite_lbu_DBSetError(glite_lbu_DBContext ctx, int code, const char *func, int line, const char *desc, ...) { - va_list ap; - - if (!code) return ctx->err.code; - - ctx->err.code = code; - free(ctx->err.desc); - 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, ctx->err.desc); - return code; -} - - -void glite_lbu_TimeToStrGeneric(time_t t, char **str, const char *amp) { - struct tm *tm = gmtime(&t); - - asprintf(str,"%s%4d-%02d-%02d %02d:%02d:%02d%s",amp,tm->tm_year+1900,tm->tm_mon+1, - tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,amp); -} - - -void glite_lbu_TimeToStr(time_t t, char **str) { - glite_lbu_TimeToStrGeneric(t, str, "'"); -} - - -void glite_lbu_TimestampToStrGeneric(double t, char **str, const char *amp) { - time_t tsec = t; - struct tm *tm = gmtime(&tsec); - - t = t - tsec + tm->tm_sec; - asprintf(str,"%s%4d-%02d-%02d %02d:%02d:%02.09f%s",amp,tm->tm_year+1900,tm->tm_mon+1, - tm->tm_mday,tm->tm_hour,tm->tm_min,t,amp); -} - - -void glite_lbu_TimestampToStr(double t, char **str) { - glite_lbu_TimestampToStrGeneric(t, str, "'"); -} - - -time_t glite_lbu_StrToTime(const char *str) { - struct tm tm; - - memset(&tm,0,sizeof(tm)); - putenv("TZ=UTC"); tzset(); - sscanf(str,"%4d-%02d-%02d %02d:%02d:%02d", - &tm.tm_year,&tm.tm_mon,&tm.tm_mday, - &tm.tm_hour,&tm.tm_min,&tm.tm_sec); - tm.tm_year -= 1900; - tm.tm_mon--; - - return mktime(&tm); -} - - -double glite_lbu_StrToTimestamp(const char *str) { - struct tm tm; - double sec; - - memset(&tm,0,sizeof(tm)); - putenv("TZ=UTC"); tzset(); - sscanf(str,"%4d-%02d-%02d %02d:%02d:%lf", - &tm.tm_year,&tm.tm_mon,&tm.tm_mday, - &tm.tm_hour,&tm.tm_min,&sec); - tm.tm_year -= 1900; - tm.tm_mon--; - tm.tm_sec = sec; - - return (sec - tm.tm_sec) + mktime(&tm); -} - - -/* ---- API ---- */ - - -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_InitDBContext(glite_lbu_DBContext *ctx, int backend) { - int ret; - - if (!VALID(backend)) return EINVAL; - if (backends[backend]->backend != backend) return ENOTSUP; - ret = backends[backend]->initContext(ctx); - if (ctx && *ctx) (*ctx)->backend = backend; - return ret; -} - - -void glite_lbu_FreeDBContext(glite_lbu_DBContext ctx) { - if (!ctx || !VALID(ctx->backend)) return; - - free(ctx->err.desc); - ctx->err.desc = NULL; - backends[ctx->backend]->freeContext(ctx); -} - - -int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->connect(ctx, cs); -} - - -void glite_lbu_DBClose(glite_lbu_DBContext ctx) { - if (!VALID(ctx->backend)) return; - backends[ctx->backend]->close(ctx); -} - - -int glite_lbu_DBQueryCaps(glite_lbu_DBContext ctx) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->queryCaps(ctx); -} - - -void glite_lbu_DBSetCaps(glite_lbu_DBContext ctx, int caps) { - if (!VALID(ctx->backend)) return; - return backends[ctx->backend]->setCaps(ctx, caps); -} - - -int glite_lbu_Transaction(glite_lbu_DBContext ctx) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->transaction(ctx); -} - - -int glite_lbu_Commit(glite_lbu_DBContext ctx) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->commit(ctx); -} - - -int glite_lbu_Rollback(glite_lbu_DBContext ctx) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->rollback(ctx); -} - - -int glite_lbu_FetchRow(glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results) { - if (!VALID(stmt->ctx->backend)) return EINVAL; - return backends[stmt->ctx->backend]->fetchRow(stmt, n, lengths, results); -} - - -void glite_lbu_FreeStmt(glite_lbu_Statement *stmt) { - if (!stmt || !*stmt || !VALID((*stmt)->ctx->backend)) return; - return backends[(*stmt)->ctx->backend]->freeStmt(stmt); -} - - -int glite_lbu_QueryIndices(glite_lbu_DBContext ctx, const char *table, char ***key_names, char ****column_names) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->queryIndices(ctx, table, key_names, column_names); -} - - -int glite_lbu_ExecSQL(glite_lbu_DBContext ctx, const char *cmd, glite_lbu_Statement *stmt) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->execSQL(ctx, cmd, stmt); -} - - -int glite_lbu_QueryColumns(glite_lbu_Statement stmt, char **cols) { - if (!VALID(stmt->ctx->backend)) return EINVAL; - return backends[stmt->ctx->backend]->queryColumns(stmt, cols); -} - - -int glite_lbu_PrepareStmt(glite_lbu_DBContext ctx, const char *sql, glite_lbu_Statement *stmt) { - if (!VALID(ctx->backend)) return EINVAL; - return backends[ctx->backend]->prepareStmt(ctx, sql, stmt); -} - - -int glite_lbu_ExecPreparedStmt_v(glite_lbu_Statement stmt, int n, va_list ap) { - if (!VALID(stmt->ctx->backend)) return EINVAL; - return backends[stmt->ctx->backend]->execPreparedStmt_v(stmt, n, ap); -} - - -int glite_lbu_ExecPreparedStmt(glite_lbu_Statement stmt, int n, ...) { - va_list ap; - int retval; - - va_start(ap, n); - retval = glite_lbu_ExecPreparedStmt_v(stmt, n, ap); - va_end(ap); - - return retval; -} - - -long int glite_lbu_Lastid(glite_lbu_Statement stmt) { - if (!VALID(stmt->ctx->backend)) return EINVAL; - return backends[stmt->ctx->backend]->lastid(stmt); -} - - -void glite_lbu_TimeToDB(glite_lbu_DBContext ctx, time_t t, char **str) { - if (!VALID(ctx->backend)) return; - return backends[ctx->backend]->timeToDB(t, str); -} - - -void glite_lbu_TimestampToDB(glite_lbu_DBContext ctx, double t, char **str) { - if (!VALID(ctx->backend)) return; - return backends[ctx->backend]->timestampToDB(t, str); -} - - -time_t glite_lbu_DBToTime(glite_lbu_DBContext ctx, const char *str) { - if (!VALID(ctx->backend)) return (time_t)-1; - return backends[ctx->backend]->DBToTime(str); -} - - -double glite_lbu_DBToTimestamp(glite_lbu_DBContext ctx, const char *str) { - if (!VALID(ctx->backend)) return -1; - return backends[ctx->backend]->DBToTimestamp(str); -} - - -#define STATUS(CTX) ((CTX)->err.code) -#define CLR_ERR(CTX) glite_lbu_DBClearError((CTX)) -int glite_lbu_bufferedInsertInit(glite_lbu_DBContext ctx, glite_lbu_bufInsert *bi, const char *table_name, long size_limit, long record_limit, const char *columns) -{ - *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) -{ - char *stmt, *vals, *temp; - long i; - - - if (!bi->rec_num) - return STATUS(bi->ctx); - - asprintf(&vals,"(%s)", bi->rows[0]); - for (i=1; i < bi->rec_num; i++) { - // XXX: use string add (preallocated memory) - asprintf(&temp,"%s,(%s)", vals, bi->rows[i]); - free(vals); vals = temp; temp = NULL; - free(bi->rows[i]); - bi->rows[i] = NULL; - } - - trio_asprintf(&stmt, "insert into %|Ss(%|Ss) values %s;", - bi->table_name, bi->columns, vals); - - if (glite_lbu_ExecSQL(bi->ctx,stmt,NULL) < 0) { - if (STATUS(bi->ctx) == EEXIST) - CLR_ERR(bi->ctx); - } - - /* reset bi counters */ - bi->rec_size = 0; - bi->rec_num = 0; - - free(vals); - free(stmt); - - return STATUS(bi->ctx); -} - - -int glite_lbu_bufferedInsert(glite_lbu_bufInsert bi, const char *row) -{ - bi->rows[bi->rec_num++] = strdup(row); - bi->rec_size += strlen(row); - - if ((bi->size_limit && bi->rec_size >= bi->size_limit) || - (bi->record_limit && bi->rec_num >= bi->record_limit)) - { - if (flush_bufferd_insert(bi)) - return STATUS(bi->ctx); - } - - return CLR_ERR(bi->ctx); -} - - -static void free_buffered_insert(glite_lbu_bufInsert bi) { - long i; - - free(bi->table_name); - free(bi->columns); - for (i=0; i < bi->rec_num; i++) { - free(bi->rows[i]); - } - free(bi->rows); -} - - -int glite_lbu_bufferedInsertClose(glite_lbu_bufInsert bi) -{ - if (flush_bufferd_insert(bi)) - return STATUS(bi->ctx); - free_buffered_insert(bi); - - return CLR_ERR(bi->ctx); -} -- 1.8.2.3