Skip to content
This repository was archived by the owner on Jul 14, 2019. It is now read-only.

Commit adcef4d

Browse files
Jason ZhouLior Amram
authored andcommitted
mysql_helper_vstmt
1 parent e3044e5 commit adcef4d

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed

include/mysql_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ void mysql_helper_connect_init(struct mysql_helper *mysql_helper);
107107
int mysql_helper_real_connect(struct mysql_helper *mysql_helper, struct mysql_login_info *login_info);
108108
int mysql_helper_connect(struct mysql_helper *mysql_helper, struct mysql_login_info *login_info);
109109
int mysql_helper_stmt(struct mysql_helper *mysql_helper, const char *query, size_t query_len, const char *params, const char *fields, ...);
110+
int mysql_helper_vstmt(struct mysql_helper *mysql_helper, const char *query, size_t query_len, const char *params, const char *fields, void ** input);
110111
int mysql_helper_stmt_col_map(struct mysql_helper *mysql_helper,
111112
const char *query, size_t query_len,
112113
void *params, struct mysql_helper_column_map *params_map, size_t nparams, /* primary params */

src/mysql_helper.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,200 @@ int mysql_helper_stmt(struct mysql_helper *mysql_helper,
315315
return 0;
316316
}
317317

318+
int mysql_helper_vstmt(struct mysql_helper *mysql_helper,
319+
const char *query,
320+
size_t query_len,
321+
const char *params,
322+
const char *fields,
323+
void **input)
324+
{
325+
/*
326+
* 0. Cleanup from previous call
327+
*/
328+
if (mysql_helper->stmt) {
329+
mysql_stmt_close(mysql_helper->stmt);
330+
mysql_helper->stmt = NULL;
331+
vmbuf_reset(&mysql_helper->buf);
332+
}
333+
/*
334+
* 1. Prepare statement
335+
*/
336+
mysql_helper->stmt = mysql_stmt_init(&mysql_helper->mysql);
337+
if (!mysql_helper->stmt)
338+
return report_error(mysql_helper);
339+
340+
if (0 != mysql_stmt_prepare(mysql_helper->stmt, query, query_len))
341+
return report_stmt_error(mysql_helper);
342+
/*
343+
* 2. Bind parameters if there are any
344+
*/
345+
uint32_t nparams = strlen(params);
346+
uint32_t n = mysql_stmt_param_count(mysql_helper->stmt);
347+
if (nparams != n) {
348+
LOGGER_ERROR("num params != num params in query (%u != %u)", nparams, n);
349+
return -1;
350+
}
351+
const char *p;
352+
uint32_t i;
353+
354+
/* TODO: move to internal vmbuf (mysql_helper), so
355+
mysql_stmt_execute can be called multiple times when inserting
356+
data */
357+
unsigned long plengths[nparams];
358+
int ptypes[nparams];
359+
my_bool pnulls[nparams];
360+
MYSQL_BIND pbind[nparams];
361+
362+
if (nparams > 0) {
363+
memset(pbind, 0, sizeof(pbind));
364+
MYSQL_BIND *pbind_ptr = pbind;
365+
for (i = 0, p = params; *p; ++p, ++pbind_ptr, ++i) {
366+
char c = *p;
367+
char *str;
368+
switch(tolower(c)) {
369+
case 'd':
370+
ptypes[i] = MYSQL_TYPE_LONG;
371+
pbind_ptr->buffer = (int *)(*input);
372+
pnulls[i] = (pbind_ptr->buffer == NULL);
373+
pbind_ptr->is_unsigned = isupper(c) ? 1 : 0;
374+
++input;
375+
break;
376+
case 'f':
377+
ptypes[i] = MYSQL_TYPE_DOUBLE;
378+
pbind_ptr->buffer = (double *)(*input);
379+
pnulls[i] = (pbind_ptr->buffer == NULL);
380+
++input;
381+
break;
382+
case 's':
383+
ptypes[i] = MYSQL_TYPE_STRING;
384+
if (isupper(c)) {
385+
plengths[i] = *(size_t *)input;
386+
str = (char *)(*input);
387+
++input;
388+
} else {
389+
str = (char *)(*input);
390+
plengths[i] = strlen(str);
391+
}
392+
pnulls[i] = (str == NULL);
393+
pbind_ptr->buffer = str;
394+
pbind_ptr->buffer_length = plengths[i];
395+
pbind_ptr->length = &plengths[i];
396+
++input;
397+
break;
398+
}
399+
pbind_ptr->buffer_type = ptypes[i];
400+
pbind_ptr->is_null = &pnulls[i];
401+
}
402+
403+
if (0 != mysql_stmt_bind_param(mysql_helper->stmt, pbind))
404+
return report_stmt_error(mysql_helper);
405+
}
406+
/*
407+
* 3. Prepare result field bindings
408+
*/
409+
uint32_t nfields = strlen(fields);
410+
MYSQL_BIND bind[nfields];
411+
unsigned long qlength[nfields];
412+
int ftypes[nfields];
413+
size_t str_ofs[nfields];
414+
415+
if (nfields > 0) {
416+
MYSQL_RES *rs = mysql_stmt_result_metadata(mysql_helper->stmt);
417+
if (!rs)
418+
return report_stmt_error(mysql_helper);
419+
n = mysql_num_fields(rs);
420+
if (n != nfields) {
421+
LOGGER_ERROR("num args != num fields in query (%u != %u)", nfields, n);
422+
mysql_free_result(rs);
423+
return -1;
424+
}
425+
mysql_helper->num_fields = n;
426+
MYSQL_FIELD *qfields = mysql_fetch_fields(rs);
427+
for (i = 0, p = fields; *p; ++p, ++i) {
428+
ftypes[i] = qfields[i].type;
429+
char c = *p;
430+
c = tolower(c);
431+
switch(c) {
432+
case 'd':
433+
ftypes[i] = MYSQL_TYPE_LONG;
434+
break;
435+
case 'f':
436+
ftypes[i] = MYSQL_TYPE_DOUBLE;
437+
break;
438+
case 's':
439+
ftypes[i] = MYSQL_TYPE_STRING;
440+
break;
441+
}
442+
qlength[i] = ribs_mysql_get_storage_size(ftypes[i], qfields[i].length);
443+
}
444+
mysql_free_result(rs);
445+
size_t data_ofs = vmbuf_alloc_aligned(&mysql_helper->buf, sizeof(char **) * nfields);
446+
size_t length_ofs = vmbuf_alloc_aligned(&mysql_helper->buf, sizeof(unsigned long) * nfields);
447+
size_t error_ofs = vmbuf_alloc_aligned(&mysql_helper->buf, sizeof(my_bool) * nfields);
448+
size_t is_null_ofs = vmbuf_alloc_aligned(&mysql_helper->buf, sizeof(my_bool) * nfields);
449+
size_t is_str_ofs = vmbuf_alloc_aligned(&mysql_helper->buf, sizeof(mysql_helper->is_str[0]) * nfields);
450+
/* allocate space for the strings */
451+
for (i = 0, p = fields; *p; ++p, ++i) {
452+
switch(tolower(*p)) {
453+
case 's':
454+
str_ofs[i] = vmbuf_alloc_aligned(&mysql_helper->buf, qlength[i] + 1);
455+
break;
456+
}
457+
}
458+
mysql_helper->data = (char **)vmbuf_data_ofs(&mysql_helper->buf, data_ofs);
459+
mysql_helper->length = (unsigned long *)vmbuf_data_ofs(&mysql_helper->buf, length_ofs);
460+
mysql_helper->is_error = (my_bool *)vmbuf_data_ofs(&mysql_helper->buf, error_ofs);
461+
mysql_helper->is_null = (my_bool *)vmbuf_data_ofs(&mysql_helper->buf, is_null_ofs);
462+
mysql_helper->is_str = (int8_t *)vmbuf_data_ofs(&mysql_helper->buf, is_str_ofs);
463+
memset(mysql_helper->is_str, 0, sizeof(mysql_helper->is_str[0]) * nfields);
464+
memset(bind, 0, sizeof(MYSQL_BIND) * nfields);
465+
MYSQL_BIND *bind_ptr = bind;
466+
for (i = 0, p = fields; *p; ++p, ++bind_ptr, ++i) {
467+
char c = *p;
468+
bind_ptr->is_unsigned = isupper(c) ? 1 : 0;
469+
bind_ptr->is_null = &mysql_helper->is_null[i];
470+
bind_ptr->error = &mysql_helper->is_error[i];
471+
bind_ptr->length = &mysql_helper->length[i];
472+
bind_ptr->buffer_type = ftypes[i];
473+
c = tolower(c);
474+
char **str;
475+
switch(c) {
476+
case 'd':
477+
bind_ptr->buffer = (int *)(*input);
478+
bind_ptr->buffer_length = sizeof(int);
479+
++input;
480+
break;
481+
case 'f':
482+
bind_ptr->buffer = (double *)(*input);
483+
bind_ptr->buffer_length = sizeof(double);
484+
++input;
485+
break;
486+
case 's':
487+
str = (char **)(*input);
488+
*str = vmbuf_data_ofs(&mysql_helper->buf, str_ofs[i]);
489+
bind_ptr->buffer = *str;
490+
bind_ptr->buffer_length = qlength[i];
491+
mysql_helper->is_str[i] = 1;
492+
++input;
493+
break;
494+
}
495+
mysql_helper->data[i] = bind_ptr->buffer;
496+
}
497+
}
498+
/*
499+
* 4. Execute the query
500+
*/
501+
if (0 != mysql_stmt_execute(mysql_helper->stmt))
502+
return report_stmt_error(mysql_helper);
503+
/*
504+
* 5. Bind result fields
505+
*/
506+
if (nfields > 0 && 0 != mysql_stmt_bind_result(mysql_helper->stmt, bind))
507+
return report_stmt_error(mysql_helper);
508+
509+
return 0;
510+
}
511+
318512
static int _mysql_helper_init_bind_map(void *data, size_t n, struct mysql_helper_column_map *map, MYSQL_BIND *pbind, unsigned long *plengths, my_bool *pnulls, struct vmbuf *tb) {
319513
if (n == 0) return 0;
320514
memset(pbind, 0, sizeof(MYSQL_BIND) * n);

0 commit comments

Comments
 (0)