From a6b92f2a4d37ae626628edf59536878d6678e756 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Milo=C5=A1=20Mula=C4=8D?= Date: Mon, 26 Jun 2006 13:56:21 +0000 Subject: [PATCH] functions for multi-row insert - needs a bit more flesh to work --- org.glite.lb.server/interface/lbs_db.h | 48 +++++++++- org.glite.lb.server/src/lbs_db.c | 154 +++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 1 deletion(-) diff --git a/org.glite.lb.server/interface/lbs_db.h b/org.glite.lb.server/interface/lbs_db.h index 14dbad8..df557c0 100644 --- a/org.glite.lb.server/interface/lbs_db.h +++ b/org.glite.lb.server/interface/lbs_db.h @@ -12,7 +12,9 @@ extern "C" { #endif -#define EDG_WLL_MYSQL_VERSION 40001 +#define EDG_WLL_MYSQL_VERSION 40001 +#define BUF_INSERT_ROW_ALLOC_BLOCK 1000 + typedef struct _edg_wll_Stmt *edg_wll_Stmt; @@ -21,6 +23,27 @@ edg_wll_ErrorCode edg_wll_DBConnect( char * /* IN: connect string user/password@host:database */ ); + +/* + * structure holds date for multi-rows insert + */ +typedef struct _edg_wll_bufInsert { + edg_wll_Context ctx; + char *table_name; + int num_cols; + char **columns; /* names of columns to be inserted into */ + long rec_num, /* actual number of rows in structure */ + rec_size; /* approx. size of a real insert string */ + long *row_len; /* array holding length of each row */ + long *row_alloc; /* size of allocated space for each row */ + char **values; /* each row hold long string with values + * inserting into one column separated with + * commas */ + long size_limit, /* size and # of records limit which trigger */ + record_limit; /* real insert; zero means unlimitted */ +} edg_wll_bufInsert; + + void edg_wll_DBClose(edg_wll_Context); @@ -84,6 +107,29 @@ int edg_wll_Transaction(edg_wll_Context ctx); int edg_wll_Commit(edg_wll_Context ctx); int edg_wll_Rollback(edg_wll_Context ctx); +/** + * Init data structure for buffered insert + * + * takes num_cols string parameters as names of columns to be inserted into + * when insert string oversize size_limit or number of rows to be inserted + * overcome record_limit, the real insert is triggered + */ +int edg_wll_bufferedInsertInit(edg_wll_Context ctx, edg_wll_bufInsert *bi, void *mysql, char *table_name, long size_limit, long record_limit, int num_cols, ...); + +/** + * adds row of n values into n columns into an insert buffer + * if num. of rows or size of data oversteps the limits, real + * multi-row insert is done + */ +edg_wll_ErrorCode edg_wll_bufferedInsert(edg_wll_bufInsert *bi, ...); + +/** + * flush buffered data and free bi structure + */ +edg_wll_ErrorCode edg_wll_bufferedInsertClose(edg_wll_bufInsert *bi); + + + #ifdef __cplusplus } #endif diff --git a/org.glite.lb.server/src/lbs_db.c b/org.glite.lb.server/src/lbs_db.c index 0aa72d2..7adf335 100644 --- a/org.glite.lb.server/src/lbs_db.c +++ b/org.glite.lb.server/src/lbs_db.c @@ -10,9 +10,12 @@ #include #include #include +#include +#include #include "lbs_db.h" #include "glite/lb/context-int.h" +#include "glite/lb/trio.h" #define DEFAULTCS "lbserver/@localhost:lbserver20" @@ -266,3 +269,154 @@ int edg_wll_Rollback(edg_wll_Context ctx) { return err; } + + +int edg_wll_bufferedInsertInit(edg_wll_Context ctx, edg_wll_bufInsert *bi, void *mysql, char *table_name, long size_limit, long record_limit, int num_cols, ...) +{ + va_list l; + long i; + + + assert(num_cols != 1); // XXX: I do not know one column multi-row insert :( + va_start(l, num_cols); + + bi->ctx = ctx; + bi->table_name = strdup(table_name); + bi->num_cols = num_cols; + bi->columns = calloc(num_cols, sizeof(*(bi->columns)) ); + bi->rec_num = 0; + bi->rec_size = 0; + bi->row_len = calloc(num_cols, sizeof(*(bi->row_len)) ); + bi->row_alloc = calloc(num_cols, sizeof(*(bi->row_alloc)) ); + bi->values = calloc(num_cols, sizeof(*(bi->values)) ); + bi->size_limit = size_limit; + bi->record_limit = record_limit; + + for (i=0; i < num_cols; i++) { + bi->columns[i] = strdup(va_arg(l,char *)); + bi->row_len[i] = 0; + bi->row_alloc[i] = 0; + } + + va_end(l); + return 0; +} + + + +static int string_add(char *what, long *used_size, long *alloc_size, char **where) +{ + long what_len = strlen(what); + int reall = 0; + + while (*used_size + what_len >= *alloc_size) { + *alloc_size += BUF_INSERT_ROW_ALLOC_BLOCK; + reall = 1; + } + + if (reall) + *where = realloc(*where, *alloc_size * sizeof(char)); + + what_len = sprintf(*where + *used_size, "%s", what); + if (what_len < 0) /* ENOMEM? */ return -1; + + *used_size += what_len; + + return 0; +} + + +static int flush_bufferd_insert(edg_wll_bufInsert *bi) +{ + char *stmt, *cols, *vals, *temp; + long i; + + asprintf(&cols,"%s", bi->columns[0]); + asprintf(&vals,"%s", bi->values[0]); + for (i=1; i < bi->num_cols; i++) { + asprintf(&temp,"%s,%s", cols, bi->columns[i]); + free(cols); cols = temp; temp = NULL; + asprintf(&temp,"%s),(%s", vals, bi->values[i]); + free(vals); vals = temp; temp = NULL; + + } + + trio_asprintf(&stmt, "insert into %|Ss(%|Ss) values (%|Ss);", + bi->table_name, cols, vals); + + // XXX:fire statement, check result, check errors + printf("\n%s\n",stmt); + + /* reset bi counters */ + bi->rec_size = 0; + bi->rec_num = 0; + for (i=0; i < bi->num_cols; i++) + bi->row_len[i] = 0; + + free(cols); + free(vals); + free(stmt); + + return 0; +} + + +/* + * adds row of n values into n columns into an insert buffer + * if num. of rows or size of data oversteps the limits, real + * multi-row insert is done + */ +edg_wll_ErrorCode edg_wll_bufferedInsert(edg_wll_bufInsert *bi, ...) +{ + va_list l; + long i; + + + va_start(l, bi); + + bi->rec_size = 0; + for (i=0; i < bi->num_cols; i++) { + if (bi->rec_num) { + if (string_add(",", &bi->row_len[i], &bi->row_alloc[i], &bi->values[i])) + return edg_wll_SetError(bi->ctx,ENOMEM,NULL);; + } + if (string_add(va_arg(l,char *), &bi->row_len[i], &bi->row_alloc[i], &bi->values[i])) + return edg_wll_SetError(bi->ctx,ENOMEM,NULL);; + bi->rec_size += bi->row_len[i]; + } + bi->rec_num++; + + 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 -1; // XXX use edg_wll_SetError(something) + } + + va_end(l); + return edg_wll_ResetError(bi->ctx); +} + +static void free_buffered_insert(edg_wll_bufInsert *bi) { + long i; + + free(bi->table_name); + for (i=0; i < bi->num_cols; i++) { + free(bi->columns[i]); + free(bi->values[i]); + } + free(bi->columns); + free(bi->values); + free(bi->row_len); + free(bi->row_alloc); +} + +edg_wll_ErrorCode edg_wll_bufferedInsertClose(edg_wll_bufInsert *bi) +{ + if (flush_bufferd_insert(bi)) + return -1; // XXX use edg_wll_SetError(something) + free_buffered_insert(bi); + + return edg_wll_ResetError(bi->ctx); +} + -- 1.8.2.3