--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "db.h"
+
+
+static void print_err(glite_jp_context_t ctx) {
+ glite_jp_error_t *e;
+
+ e = ctx->error;
+ while (e) {
+ printf("%s(%s)\n", e->desc, e->source);
+ e = e->reason;
+ }
+ printf("\n");
+}
+
+
+int main() {
+ glite_jp_context_t ctx;
+ glite_jp_db_stmt_t jpstmt;
+
+ glite_jp_init_context(&ctx);
+
+ printf("connecting...\n");
+ if (glite_jp_db_connect(ctx, "jpis/@localhost:jpis1") != 0) goto fail;
+
+ // "trio" queries
+{
+ int nr, i;
+ char **res;
+
+ printf("selecting...\n");
+ if ((glite_jp_db_execstmt(ctx, "SELECT uniqueid, feedid, state, source, condition FROM feeds", &jpstmt)) == -1) goto fail;
+
+ printf("fetching...\n");
+ res = calloc(4, sizeof(char *));
+ while ((nr = glite_jp_db_fetchrow(jpstmt, res)) > 0) {
+ printf("Result: n=%d, res=%p\n", nr, res);
+ i = 0;
+ if (res) while(i < nr) {printf("p=%p(%s)\n", res[i], res[i]);free(res[i]);i++;}
+ }
+ free(res);
+ printf("closing stmt...\n");
+ glite_jp_db_freestmt(&jpstmt);
+}
+
+ // param queries
+{
+ char res_feedid[33];
+ long int res_state;
+ char res_source[256];
+ char res_condition[1024];
+ unsigned long res_condition_length;
+ long int param_state;
+
+ void *my_res, *my_param;
+
+ glite_jp_db_create_params(&my_param, 1, GLITE_JP_DB_TYPE_INT, ¶m_state);
+ glite_jp_db_create_results(&my_res, 4,
+ GLITE_JP_DB_TYPE_VARCHAR, NULL, res_feedid, sizeof(res_feedid), NULL,
+ GLITE_JP_DB_TYPE_INT, NULL, &res_state,
+ GLITE_JP_DB_TYPE_VARCHAR, NULL, res_source, sizeof(res_source), NULL,
+ GLITE_JP_DB_TYPE_MEDIUMBLOB, NULL, res_condition, sizeof(res_condition), &res_condition_length
+ );
+ printf("preparing...\n");
+ if ((glite_jp_db_prepare(ctx, "SELECT feedid, state, source, condition FROM feeds WHERE state = ?", &jpstmt, my_param, my_res)) != 0) goto fail_close;
+
+ param_state = 1;
+ printf("executing state %ld...\n", param_state);
+ if (glite_jp_db_execute(jpstmt) == -1) {
+ glite_jp_db_freestmt(&jpstmt);
+ goto fail_stmtclose;
+ }
+ printf("fetching...\n");
+ while (glite_jp_db_fetch(jpstmt) == 0) {
+ printf("feedid:%s, state:%ld, source:%s, condition:%s\n", res_feedid, res_state, res_source, res_condition);
+ }
+
+ param_state = 2;
+ printf("executing state %ld...\n", param_state);
+ if (glite_jp_db_execute(jpstmt) == -1) {
+ glite_jp_db_freestmt(&jpstmt);
+ goto fail_stmtclose;
+ }
+ printf("fetching...\n");
+ while (glite_jp_db_fetch(jpstmt) == 0) {
+ printf("feedid:%s, state:%ld, source:%s, condition:%s\n", res_feedid, res_state, res_source, res_condition);
+ }
+}
+
+ printf("closing stmt...\n");
+ glite_jp_db_freestmt(&jpstmt);
+ printf("closing...\n");
+ glite_jp_db_close(ctx);
+
+ glite_jp_free_context(ctx);
+ return 0;
+
+fail_stmtclose:
+ printf("closing stmt...\n");
+ glite_jp_db_freestmt(&jpstmt);
+fail_close:
+ printf("closing...\n");
+ glite_jp_db_close(ctx);
+fail:
+ printf("failed\n");
+ print_err(ctx);
+ glite_jp_free_context(ctx);
+
+ return 1;
+}
extern "C" {
#endif
+#include <glite/jp/types.h>
+#include <glite/jp/context.h>
typedef struct _glite_jp_db_stmt_t *glite_jp_db_stmt_t;
+typedef enum {
+ GLITE_JP_DB_TYPE_NULL = 0,
+ GLITE_JP_DB_TYPE_TINYINT = 1,
+ GLITE_JP_DB_TYPE_INT = 2,
+ GLITE_JP_DB_TYPE_TINYBLOB = 3,
+ GLITE_JP_DB_TYPE_TINYTEXT = 4,
+ GLITE_JP_DB_TYPE_BLOB = 5,
+ GLITE_JP_DB_TYPE_TEXT = 6,
+ GLITE_JP_DB_TYPE_MEDIUMBLOB = 7,
+ GLITE_JP_DB_TYPE_MEDIUMTEXT = 8,
+ GLITE_JP_DB_TYPE_LONGBLOB = 9,
+ GLITE_JP_DB_TYPE_LONGTEXT = 10,
+ GLITE_JP_DB_TYPE_VARCHAR = 11,
+ GLITE_JP_DB_TYPE_CHAR = 12,
+ GLITE_JP_DB_TYPE_DATE = 13,
+ GLITE_JP_DB_TYPE_TIME = 14,
+ GLITE_JP_DB_TYPE_DATETIME = 15,
+ GLITE_JP_DB_TYPE_TIMESTAMP = 16,
+ GLITE_JP_DB_TYPE_LAST = 17
+} glite_jp_db_type_t;
/**
* Connect to the database.
*
\return JP error code
*/
-int glite_jp_db_connect(glite_jp_context_t,const char *);
+int glite_jp_db_connect(glite_jp_context_t, const char *);
/**
/**
- * Free the statement structure
+ * Free the statement structure and destroy its parameters.
*
* \param[inout] stmt statement
*/
/**
- * Assign parameters to mysql bind structure.
+ * Create and assign parameters for mysql prepared commands.
*
- * \param[inout] param mysql bind strusture array
- * \param[in] type mysql type
+ * \param[out] params internal structure array
*
* Variable parameters:
- * MYSQL_TYPE_TINY: char *buffer
- * MYSQL_TYPE_LONG: long int *buffer
- * MYSQL_TYPE_*_BLOB: void *buffer, unsigned long *length
- * MYSQL_TYPE_*STRING: char *buffer, unsigned long *length
- * MYSQL_TYPE_NULL: -
+ * always:
+ * glite_jp_db_type_t type DB item type
+ * then one of them:
+ * GLITE_JP_DB_TYPE_TINYINT: char *buffer
+ * GLITE_JP_DB_TYPE_INT: int *buffer
+ * GLITE_JP_DB_TYPE_*BLOB/TEXT: void *buffer, unsigned long *length
+ * GLITE_JP_DB_TYPE_[VAR]CHAR: char *buffer, unsigned long *length
+ * GLITE_JP_DB_TYPE_DATE: void **buffer
+ * GLITE_JP_DB_TYPE_TIME: void **buffer
+ * GLITE_JP_DB_TYPE_DATETIME: void **buffer
+ * GLITE_JP_DB_TYPE_TIMESTAMP: void **buffer
+ * GLITE_JP_DB_TYPE_NULL: -
*/
-void glite_jp_db_assign_param(MYSQL_BIND *param, enum enum_field_types type, ...);
-
+void glite_jp_db_create_params(void **params, int n, ...);
/**
- * Assign result variables to mysql bind structure.
+ * Create and assign result variables for mysql prepared commands.
*
* \param[inout] result mysql bind strusture array
- * \param[in] type mysql type
- * \param[in] is_null pointer to is_null boolean
*
* Variable parameters:
- * MYSQL_TYPE_TINY: char *buffer
- * MYSQL_TYPE_LONG: long int *buffer
- * MYSQL_TYPE_*_BLOB: void *buffer, unsigned long max_length, unsigned long *length
- * MYSQL_TYPE_*STRING: char *buffer, unsigned long max_length, unsigned long *length
+ * always:
+ * \param[in] glite_jp_db_type_t type DB item type
+ * \param[in] int *is_null pointer to is_null boolean or NULL
+ * then one of them:
+ * GLITE_JP_DB_TYPE_TINYINT: char *buffer
+ * GLITE_JP_DB_TYPE_INT: long int *buffer
+ * GLITE_JP_DB_TYPE_*BLOB/TEXT: void *buffer, unsigned long max_length, unsigned long *length
+ * GLITE_JP_DB_TYPE_[VAR]CHAR: char *buffer, unsigned long max_length, unsigned long *length
+ * GLITE_JP_DB_TYPE_DATE: void **buffer
+ * GLITE_JP_DB_TYPE_TIME: void **buffer
+ * GLITE_JP_DB_TYPE_DATETIME: void **buffer
+ * GLITE_JP_DB_TYPE_TIMESTAMP: void **buffer
+ */
+void glite_jp_db_create_results(void **results, int n, ...);
+
+/**
+ * Destroy prepared parameters.
+ */
+void glite_jp_db_destroy_params(void *params);
+
+/**
+ * Destroy prepared results.
*/
+void glite_jp_db_destroy_results(void *results);
+
+#if 0
+void glite_jp_db_assign_param(MYSQL_BIND *param, enum enum_field_types type, ...);
void glite_jp_db_assign_result(MYSQL_BIND *result, enum enum_field_types type, my_bool *is_null, ...);
+#endif
+
+/**
+ * Assign time_t to buffer.
+ */
+void glite_jp_db_set_time(void *buffer, const time_t time);
+
+/**
+ * Get the time from buffer.
+ */
+time_t glite_jp_db_get_time(const void *buffer);
+
+/**
+ * Rebind the parameters and/or results.
+ *
+ * \param[inout] jpstmt JP SQL statement to work with
+ * \param[inout] params mysql static structure with parameters or NULL
+ * \param[inout] cols mysql static structure with result buffer or NULL
+ *
+ * \return JP error code
+ */
+int glite_jp_db_rebind(glite_jp_db_stmt_t jpstmt, void *params, void *cols);
/**
* Prepare the SQL statement. Use glite_jp_db_freestmt() to free it.
* \param[inout] ctx context to work with
* \param[in] sql SQL command
* \param[out] jpstmt returned JP SQL statement
- * \param[inout] params mysql static structure with parameters
- * \param[inout] cols mysql static structure with result buffer
+ * \param[inout] params mysql static structure with parameters or NULL
+ * \param[inout] cols mysql static structure with result buffer or NULL
*
* \return JP error code
*/
-int glite_jpis_db_prepare(glite_jp_context_t ctx, const char *sql, glite_jp_db_stmt_t *jpstmt, MYSQL_BIND *params, MYSQL_BIND *cols);
+int glite_jp_db_prepare(glite_jp_context_t ctx, const char *sql, glite_jp_db_stmt_t *jpstmt, void *params, void *cols);
/**
* Execute prepared SQL statement.
#ident "$Header$"
-#include "mysql.h"
-#include "mysqld_error.h"
-#include "errmsg.h"
+#include <mysql.h>
+#include <mysqld_error.h>
+#include <errmsg.h>
#include <sys/types.h>
#include <stdio.h>
#include "db.h"
-#define GLITE_JP_LB_MYSQL_VERSION 40018
+
+#define GLITE_JP_DB_MYSQL_VERSION 40102
+
+#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID < GLITE_JP_DB_MYSQL_VERSION
+#error required MySQL version 4.1.2
+#endif
#define JP_ERR(CTX, CODE, DESC) jp_err((CTX), (CODE), (DESC), __FUNCTION__, __LINE__)
#define MY_ERR(CTX) my_err((CTX), __FUNCTION__, __LINE__)
#define MY_ISOKSTMT(JPSTMT, RETRY) my_isokstmt((JPSTMT), __FUNCTION__, __LINE__, (RETRY))
+typedef struct {
+ int n;
+ MYSQL_BIND params[1];
+} params_t;
+
struct _glite_jp_db_stmt_t {
glite_jp_context_t ctx;
MYSQL_RES *result;
MYSQL_STMT *stmt;
+ params_t *params, *results;
+};
+
+
+static int glite_to_mysql_type[] = {
+ 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,
};
char *slash,*at,*colon;
int ret;
+ // needed for SQL result parameters
+ assert(sizeof(int) >= sizeof(my_bool));
+
glite_jp_clear_error(ctx);
if (!cs) return JP_ERR(ctx, EINVAL, "connect string not specified");
if (!slash || !at || !colon) {
free(buf);
- mysql_close((MYSQL *)ctx->dbhandle);
+ glite_jp_db_close(ctx);
return JP_ERR(ctx, EINVAL, "Invalid DB connect string");
}
if (!mysql_real_connect((MYSQL *) ctx->dbhandle,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) {
free(buf);
ret = MY_ERR(ctx);
- mysql_close((MYSQL *)ctx->dbhandle);
+ glite_jp_db_close(ctx);
return ret;
}
-
free(buf);
+
+ if ((ret = glite_jp_db_dbcheckversion(ctx)) != 0) {
+ glite_jp_db_close(ctx);
+ return ret;
+ }
+
return 0;
}
void glite_jp_db_close(glite_jp_context_t ctx)
{
- mysql_close((MYSQL *) ctx->dbhandle);
- ctx->dbhandle = NULL;
+ if (ctx->dbhandle) {
+ mysql_close((MYSQL *) ctx->dbhandle);
+ ctx->dbhandle = NULL;
+ }
}
if (*stmt) {
if ((**stmt).result) mysql_free_result((**stmt).result);
if ((*stmt)->stmt) mysql_stmt_close((*stmt)->stmt);
+ if ((*stmt)->params) glite_jp_db_destroy_params((*stmt)->params);
+ if ((*stmt)->results) glite_jp_db_destroy_results((*stmt)->results);
free(*stmt);
*stmt = NULL;
}
version = 10000*major + 100*minor + sub;
- if (version < GLITE_JP_LB_MYSQL_VERSION) {
+ if (version < GLITE_JP_DB_MYSQL_VERSION) {
char msg[300];
return JP_ERR(ctx, EINVAL, msg);
}
-void glite_jp_db_assign_param(MYSQL_BIND *param, enum enum_field_types type, ...) {
+void glite_jp_db_create_params(void **params, int n, ...) {
+ params_t *myparams;
+ MYSQL_BIND *myparam;
+ MYSQL_TIME **mytime;
+ int i;
va_list ap;
+ glite_jp_db_type_t type;
- memset(param, 0, sizeof(*param));
- param->buffer_type = type;
+ myparams = calloc(n, sizeof(params_t) + (n - 1) * sizeof(MYSQL_BIND));
+ va_start(ap, n);
- va_start(ap, type);
+ for (i = 0; i < n; i++) {
+ myparam = myparams->params + i;
+ type = va_arg(ap, glite_jp_db_type_t);
- switch (type) {
- case MYSQL_TYPE_TINY:
- param->buffer = va_arg(ap, char *);
- break;
+ switch (type) {
+ case GLITE_JP_DB_TYPE_TINYINT:
+ myparam->buffer = va_arg(ap, char *);
+ break;
- case MYSQL_TYPE_LONG:
- param->buffer = va_arg(ap, long int *);
- break;
+ case GLITE_JP_DB_TYPE_INT:
+ myparam->buffer = va_arg(ap, long int *);
+ break;
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- param->buffer = va_arg(ap, void *);
- param->length = va_arg(ap, unsigned long *);
- break;
+ case GLITE_JP_DB_TYPE_TINYBLOB:
+ case GLITE_JP_DB_TYPE_TINYTEXT:
+ case GLITE_JP_DB_TYPE_BLOB:
+ case GLITE_JP_DB_TYPE_TEXT:
+ case GLITE_JP_DB_TYPE_MEDIUMBLOB:
+ case GLITE_JP_DB_TYPE_MEDIUMTEXT:
+ case GLITE_JP_DB_TYPE_LONGBLOB:
+ case GLITE_JP_DB_TYPE_LONGTEXT:
+ myparam->buffer = va_arg(ap, void *);
+ myparam->length = va_arg(ap, unsigned long *);
+ break;
+
+ case GLITE_JP_DB_TYPE_VARCHAR:
+ case GLITE_JP_DB_TYPE_CHAR:
+ myparam->buffer = va_arg(ap, char *);
+ myparam->length = va_arg(ap, unsigned long *);
+ break;
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- param->buffer = va_arg(ap, char *);
- param->length = va_arg(ap, unsigned long *);
- break;
+ case GLITE_JP_DB_TYPE_DATE:
+ case GLITE_JP_DB_TYPE_TIME:
+ case GLITE_JP_DB_TYPE_DATETIME:
+ case GLITE_JP_DB_TYPE_TIMESTAMP:
+ mytime = (MYSQL_TIME **)va_arg(ap, void **);
+ *mytime = calloc(1, sizeof(MYSQL_TIME));
+ myparam->buffer = *mytime;
+ break;
- case MYSQL_TYPE_NULL:
- break;
+ case GLITE_JP_DB_TYPE_NULL:
+ break;
- default:
- assert("unimplemented parameter assign" == NULL);
- break;
+ default:
+ assert("unimplemented parameter assign" == NULL);
+ break;
+ }
+ myparam->buffer_type = glite_to_mysql_type[type];
}
+ myparams->n = n;
va_end(ap);
+ *params = myparams;
}
-void glite_jp_db_assign_result(MYSQL_BIND *param, enum enum_field_types type, my_bool *is_null, ...) {
+
+void glite_jp_db_create_results(void **results, int n, ...) {
+ params_t *myresults;
+ MYSQL_BIND *myresult;
+ MYSQL_TIME **mytime;
va_list ap;
+ int i;
+ glite_jp_db_type_t type;
+ int *is_null;
+
+ myresults = calloc(n, sizeof(params_t) + (n - 1) * sizeof(MYSQL_BIND));
+ va_start(ap, n);
+
+ for (i = 0; i < n; i++) {
+ myresult = myresults->params + i;
+ type = va_arg(ap, glite_jp_db_type_t);
+ is_null = va_arg(ap, int *);
+ myresult->is_null = (my_bool *)is_null;
+ if (is_null) *is_null = 0;
+
+ switch(type) {
+ case GLITE_JP_DB_TYPE_TINYINT:
+ myresult->buffer = va_arg(ap, char *);
+ myresult->buffer_length = sizeof(char);
+ break;
+
+ case GLITE_JP_DB_TYPE_INT:
+ myresult->buffer = va_arg(ap, long int *);
+ myresult->buffer_length = sizeof(long int);
+ break;
+
+ case GLITE_JP_DB_TYPE_TINYBLOB:
+ case GLITE_JP_DB_TYPE_TINYTEXT:
+ case GLITE_JP_DB_TYPE_BLOB:
+ case GLITE_JP_DB_TYPE_TEXT:
+ case GLITE_JP_DB_TYPE_MEDIUMBLOB:
+ case GLITE_JP_DB_TYPE_MEDIUMTEXT:
+ case GLITE_JP_DB_TYPE_LONGBLOB:
+ case GLITE_JP_DB_TYPE_LONGTEXT:
+ myresult->buffer = va_arg(ap, void *);
+ myresult->buffer_length = va_arg(ap, unsigned long);
+ myresult->length = va_arg(ap, unsigned long *);
+ break;
- memset(param, 0, sizeof(*param));
- param->buffer_type = type;
- param->is_null = is_null;
-
- va_start(ap, is_null);
-
- switch(type) {
- case MYSQL_TYPE_TINY:
- param->buffer = va_arg(ap, char *);
- param->buffer_length = sizeof(char);
- break;
-
- case MYSQL_TYPE_LONG:
- param->buffer = va_arg(ap, long int *);
- param->buffer_length = sizeof(long int);
- break;
-
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- param->buffer = va_arg(ap, void *);
- param->buffer_length = va_arg(ap, unsigned long);
- param->length = va_arg(ap, unsigned long *);
- break;
-
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- param->buffer = va_arg(ap, char *);
- param->buffer_length = va_arg(ap, unsigned long);
- param->length = va_arg(ap, unsigned long *);
- break;
-
- default:
- assert("unimplemented result assign" == NULL);
+ case GLITE_JP_DB_TYPE_VARCHAR:
+ case GLITE_JP_DB_TYPE_CHAR:
+ myresult->buffer = va_arg(ap, char *);
+ myresult->buffer_length = va_arg(ap, unsigned long);
+ myresult->length = va_arg(ap, unsigned long *);
+ break;
+
+ case GLITE_JP_DB_TYPE_DATE:
+ case GLITE_JP_DB_TYPE_TIME:
+ case GLITE_JP_DB_TYPE_DATETIME:
+ case GLITE_JP_DB_TYPE_TIMESTAMP:
+ mytime = (MYSQL_TIME **)va_arg(ap, void **);
+ *mytime = calloc(1, sizeof(MYSQL_TIME));
+ myresult->buffer = *mytime;
+ break;
+
+ default:
+ assert("unimplemented result assign" == NULL);
+ }
+ myresult->buffer_type = glite_to_mysql_type[type];
+ if (myresult->buffer && myresult->buffer_length) memset(myresult->buffer, 0, myresult->buffer_length);
}
- if (param->buffer && param->buffer_length) memset(param->buffer, 0, param->buffer_length);
+ myresults->n = n;
va_end(ap);
+ *results = myresults;
}
-int glite_jp_db_prepare(glite_jp_context_t ctx, const char *sql, glite_jp_db_stmt_t *jpstmt, MYSQL_BIND *params, MYSQL_BIND *cols) {
+static void glite_jp_db_destroy_respam(params_t *params) {
+ MYSQL_BIND *myparam;
+ int i;
+ enum enum_field_types type;
+
+ for (i = 0; i < params->n; i++) {
+ myparam = params->params + i;
+ type = myparam->buffer_type;
+ if (type == MYSQL_TYPE_DATE || type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATETIME || type == MYSQL_TYPE_TIMESTAMP) {
+ free(myparam->buffer);
+ myparam->buffer = NULL;
+ }
+ }
+ free(params);
+}
+
+
+void glite_jp_db_destroy_params(void *params) {
+ glite_jp_db_destroy_respam(params);
+}
+
+
+void glite_jp_db_destroy_results(void *results) {
+ glite_jp_db_destroy_respam(results);
+}
+
+
+void glite_jp_db_set_time(void *buffer, const time_t time) {
+ MYSQL_TIME *mybuffer;
+ struct tm tm;
+
+ mybuffer = (MYSQL_TIME *)buffer;
+ gmtime_r(&time, &tm);
+ mybuffer->year = tm.tm_year + 1900;
+ mybuffer->month = tm.tm_mon + 1;
+ mybuffer->day = tm.tm_mday;
+ mybuffer->hour = tm.tm_hour;
+ mybuffer->minute = tm.tm_min;
+ mybuffer->second = tm.tm_sec;
+}
+
+
+time_t glite_jp_db_get_time(const void *buffer) {
+ MYSQL_TIME *mybuffer;
+ struct tm tm;
+
+ mybuffer = (MYSQL_TIME *)buffer;
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = mybuffer->year - 1900;
+ tm.tm_mon = mybuffer->month - 1;
+ tm.tm_mday = mybuffer->day;
+ tm.tm_hour = mybuffer->hour;
+ tm.tm_min = mybuffer->minute;
+ tm.tm_sec = mybuffer->second;
+
+ return mktime(&tm);
+}
+
+
+int glite_jp_db_rebind(glite_jp_db_stmt_t jpstmt, void *params, void *cols) {
+ if (jpstmt->params) {
+ glite_jp_db_destroy_params(jpstmt->params);
+ jpstmt->params = NULL;
+ }
+ if (jpstmt->results) {
+ glite_jp_db_destroy_results(jpstmt->results);
+ jpstmt->results = NULL;
+ }
+ if (params) {
+ jpstmt->params = (params_t *)params;
+ if (mysql_stmt_bind_param(jpstmt->stmt, jpstmt->params->params) != 0) return MY_ERRSTMT(jpstmt);
+ }
+ if (cols) {
+ jpstmt->results = (params_t *)cols;
+ if (mysql_stmt_bind_result(jpstmt->stmt, jpstmt->results->params) != 0) return MY_ERRSTMT(jpstmt);
+ }
+
+ return 0;
+}
+
+
+int glite_jp_db_prepare(glite_jp_context_t ctx, const char *sql, glite_jp_db_stmt_t *jpstmt, void *params, void *cols) {
int ret, retry;
glite_jp_clear_error(ctx);
// init
- *jpstmt = malloc(sizeof(struct _glite_jp_db_stmt_t));
+ *jpstmt = calloc(1, sizeof(struct _glite_jp_db_stmt_t));
(*jpstmt)->ctx = ctx;
- (*jpstmt)->result = NULL;
// create the SQL command
- if (((*jpstmt)->stmt = mysql_stmt_init((MYSQL *)ctx->dbhandle)) == NULL)
- return MY_ERRSTMT(*jpstmt);
+ if (((*jpstmt)->stmt = mysql_stmt_init((MYSQL *)ctx->dbhandle)) == NULL) {
+ ret = MY_ERRSTMT(*jpstmt);
+ goto failed;
+ }
// prepare the SQL command
retry = 1;
} while (ret == 0);
if (ret == -1) goto failed;
- // parameters
- if (params) {
- if (mysql_stmt_bind_param((*jpstmt)->stmt, params) != 0)
- return MY_ERRSTMT(*jpstmt);
- }
-
- // results
- if (cols) {
- if (mysql_stmt_bind_result((*jpstmt)->stmt, cols) != 0)
- return MY_ERRSTMT(*jpstmt);
- }
+ // parameters and results
+ if ((ret = glite_jp_db_rebind(*jpstmt, params, cols)) != 0) goto failed;
return 0;
failed:
+ if (params) glite_jp_db_destroy_params(params);
+ if (cols) glite_jp_db_destroy_params(cols);
+ glite_jp_db_freestmt(jpstmt);
return ctx->error->code;
}