68 #include <mysqld_error.h> 72 #if MYSQL_VERSION_ID >= 80000 && !defined(MARIADB_BASE_VERSION) 84 static inline int mysql_er_temp(
const int rc)
87 case ER_LOCK_WAIT_TIMEOUT:
88 case ER_LOCK_DEADLOCK:
89 case ER_GET_TEMPORARY_ERRMSG:
101 static void *mysql_open_conn(
const DBConf *db_conf)
111 mysql = gw_malloc(
sizeof(MYSQL));
115 if (!mysql_init(mysql)) {
116 error(0,
"MYSQL: init failed!");
117 error(0,
"MYSQL: %s", mysql_error(mysql));
125 conf->
port, NULL, 0)) {
126 error(0,
"MYSQL: can not connect to database!");
127 error(0,
"MYSQL: %s", mysql_error(mysql));
132 info(0,
"MYSQL: server version %s, client version %s.",
133 mysql_get_server_info(mysql), mysql_get_client_info());
144 static void mysql_close_conn(
void *conn)
149 mysql_close((MYSQL*) conn);
154 static int mysql_check_conn(
void *conn)
159 if (mysql_ping((MYSQL*) conn)) {
160 error(0,
"MYSQL: database check failed!");
161 error(0,
"MYSQL: %s", mysql_error(conn));
169 static int mysql_select(
void *conn,
const Octstr *sql,
List *binds,
List **res)
173 MYSQL_BIND *bind = NULL;
180 stmt = mysql_stmt_init((MYSQL*) conn);
182 error(0,
"MYSQL: mysql_stmt_init(), out of memory.");
186 error(0,
"MYSQL: Unable to prepare statement: %s", mysql_stmt_error(stmt));
187 mysql_stmt_close(stmt);
193 bind = gw_malloc(
sizeof(MYSQL_BIND) * binds_len);
194 memset(bind, 0,
sizeof(MYSQL_BIND) * binds_len);
195 for (i = 0; i < binds_len; i++) {
198 bind[i].buffer_type = MYSQL_TYPE_STRING;
203 if (mysql_stmt_bind_param(stmt, bind)) {
204 error(0,
"MYSQL: mysql_stmt_bind_param() failed: `%s'", mysql_stmt_error(stmt));
206 mysql_stmt_close(stmt);
212 if (mysql_stmt_execute(stmt)) {
213 error(0,
"MYSQL: mysql_stmt_execute() failed: `%s'", mysql_stmt_error(stmt));
215 mysql_stmt_close(stmt);
220 #define DESTROY_BIND(bind, binds_len) \ 223 for (i = 0; i < binds_len; i++) { \ 224 gw_free(bind[i].buffer); \ 225 gw_free(bind[i].length); \ 226 gw_free(bind[i].is_null); \ 232 result = mysql_stmt_result_metadata(stmt);
234 error(0,
"MYSQL: mysql_stmt_result_metadata() failed: `%s'", mysql_stmt_error(stmt));
235 mysql_stmt_close(stmt);
239 binds_len = mysql_num_fields(result);
240 bind = gw_malloc(
sizeof(MYSQL_BIND) * binds_len);
241 memset(bind, 0,
sizeof(MYSQL_BIND) * binds_len);
243 for (i = 0; i < binds_len; i++) {
244 MYSQL_FIELD *field = mysql_fetch_field(result);
246 debug(
"gwlib.dbpool_mysql", 0,
"column=%s buffer_type=%d max_length=%ld length=%ld", field->name, field->type, field->max_length, field->length);
248 switch(field->type) {
249 case MYSQL_TYPE_TIME:
250 case MYSQL_TYPE_DATE:
251 case MYSQL_TYPE_DATETIME:
252 case MYSQL_TYPE_TIMESTAMP:
253 bind[i].buffer_type = field->type;
254 bind[i].buffer = (
char*)gw_malloc(
sizeof(MYSQL_TIME));
255 bind[i].is_null = gw_malloc(
sizeof(my_bool));
256 bind[i].length = gw_malloc(
sizeof(
unsigned long));
259 bind[i].buffer_type = MYSQL_TYPE_STRING;
260 bind[i].buffer = gw_malloc(field->length);
261 bind[i].buffer_length = field->length;
262 bind[i].length = gw_malloc(
sizeof(
unsigned long));
263 bind[i].is_null = gw_malloc(
sizeof(my_bool));
267 mysql_free_result(result);
269 if (mysql_stmt_bind_result(stmt, bind)) {
270 error(0,
"MYSQL: mysql_stmt_bind_result() failed: `%s'", mysql_stmt_error(stmt));
271 DESTROY_BIND(bind, binds_len);
272 mysql_stmt_close(stmt);
277 while(!(ret = mysql_stmt_fetch(stmt))) {
279 for (i = 0; i < binds_len; i++) {
283 if (*bind[i].is_null) {
288 switch(bind[i].buffer_type) {
289 case MYSQL_TYPE_DATE:
291 str =
octstr_format(
"%04d-%02d-%02d", ts->year, ts->month, ts->day);
293 case MYSQL_TYPE_TIME:
294 case MYSQL_TYPE_DATETIME:
295 case MYSQL_TYPE_TIMESTAMP:
297 str =
octstr_format(
"%04d-%02d-%02d %02d:%02d:%02d", ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second);
300 if (bind[i].length == 0)
310 DESTROY_BIND(bind, binds_len);
314 if (ret != MYSQL_NO_DATA) {
316 error(0,
"MYSQL: mysql_stmt_bind_result() failed: `%s'", mysql_stmt_error(stmt));
317 mysql_stmt_close(stmt);
325 mysql_stmt_close(stmt);
331 static int mysql_update(
void *conn,
const Octstr *sql,
List *binds)
334 MYSQL_BIND *bind = NULL;
339 stmt = mysql_stmt_init((MYSQL*) conn);
341 error(0,
"MYSQL: mysql_stmt_init(), out of memory.");
345 error(0,
"MYSQL: Unable to prepare statement: `%s'", mysql_stmt_error(stmt));
346 mysql_stmt_close(stmt);
352 bind = gw_malloc(
sizeof(MYSQL_BIND) * binds_len);
353 memset(bind, 0,
sizeof(MYSQL_BIND) * binds_len);
354 for (i = 0; i < binds_len; i++) {
357 bind[i].buffer_type = MYSQL_TYPE_STRING;
362 if (mysql_stmt_bind_param(stmt, bind)) {
363 error(0,
"MYSQL: mysql_stmt_bind_param() failed: `%s'", mysql_stmt_error(stmt));
365 mysql_stmt_close(stmt);
372 ret = mysql_stmt_execute(stmt);
374 ret = mysql_stmt_errno(stmt);
375 if (mysql_er_temp(ret)) {
376 warning(0,
"MYSQL: mysql_stmt_execute() failed: %d: `%s'. Retrying.", ret, mysql_stmt_error(stmt));
380 error(0,
"MYSQL: mysql_stmt_execute() failed: %d: `%s'", ret, mysql_stmt_error(stmt));
382 mysql_stmt_close(stmt);
388 ret = mysql_stmt_affected_rows(stmt);
389 mysql_stmt_close(stmt);
395 static void mysql_conf_destroy(
DBConf *db_conf)
409 static struct db_ops mysql_ops = {
410 .
open = mysql_open_conn,
411 .close = mysql_close_conn,
412 .check = mysql_check_conn,
413 .select = mysql_select,
414 .update = mysql_update,
415 .conf_destroy = mysql_conf_destroy
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
gw_assert(wtls_machine->packet_to_send !=NULL)
void gwlist_produce(List *list, void *item)
long gwlist_len(List *list)
void * gwlist_get(List *list, long pos)
#define octstr_get_cstr(ostr)
void * gwlist_extract_first(List *list)
void warning(int err, const char *fmt,...)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
#define octstr_create(cstr)
void octstr_destroy_item(void *os)
long octstr_len(const Octstr *ostr)
void debug(const char *place, int err, const char *fmt,...)
#define octstr_create_from_data(data, len)
void *(* open)(const DBConf *conf)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)