driver-mysql.c revision bd63b5b860658b01b1f46f26d406e1e4a9dc019a
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen/* ugly way to tell clang that mysql.h is a system header and we don't want
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen to enable nonnull attributes for it by default.. */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen const char *user, *password, *dbname, *host, *unix_socket;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen const char *ssl_cert, *ssl_key, *ssl_ca, *ssl_ca_path, *ssl_cipher;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenextern const struct sql_result driver_mysql_result;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenextern const struct sql_result driver_mysql_error_result;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic const char *mysql_prefix(struct mysql_db *db)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen return t_strdup_printf("mysql(%s)", db->host);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic int driver_mysql_connect(struct sql_db *_db)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen unsigned long client_flags = db->client_flags;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_assert(db->api.state == SQL_DB_STATE_DISCONNECTED);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_CONNECTING);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen mysql_options(db->mysql, MYSQL_READ_DEFAULT_FILE,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen mysql_options(db->mysql, MYSQL_READ_DEFAULT_GROUP,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen db->option_group != NULL ? db->option_group : "client");
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen if (!db->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen mysql_ssl_set(db->mysql, db->ssl_key, db->ssl_cert,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen "(remove ssl_ca and ssl_ca_path settings)");
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* CLIENT_MULTI_RESULTS allows the use of stored procedures */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen failed = mysql_real_connect(db->mysql, host, db->user, db->password,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen secs_used = SQL_CONNECT_TIMEOUT_SECS - alarm(0);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* connecting could have taken a while. make sure that any
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen timeouts that get added soon will get a refreshed
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen timestamp. */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_error("%s: Connect failed to database (%s): %s - "
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen "waiting for %u seconds before retry",
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen mysql_error(db->mysql), db->api.connect_delay);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_info("%s: Connected to database %s%s", mysql_prefix(db),
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void driver_mysql_disconnect(struct sql_db *_db ATTR_UNUSED)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void driver_mysql_parse_connect_string(struct mysql_db *db,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen const char **field;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen args = t_strsplit_spaces(connect_string, " ");
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_fatal("mysql: Missing value in connect string: %s",
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_fatal("mysql: Unknown connect string: %s", name);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_fatal("mysql: No hosts given in connect string");
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic struct sql_db *driver_mysql_init_v(const char *connect_string)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen pool = pool_alloconly_create("mysql driver", 1024);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void driver_mysql_deinit_v(struct sql_db *_db)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic int driver_mysql_do_query(struct mysql_db *db, const char *query)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic const char *
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainendriver_mysql_escape_string(struct sql_db *_db, const char *string)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen if (_db->state == SQL_DB_STATE_DISCONNECTED) {
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* try connecting */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* FIXME: we don't have a valid connection, so fallback
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen to using default escaping. the next query will most
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen likely fail anyway so it shouldn't matter that much
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen what we return here.. Anyway, this API needs
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen changing so that the escaping function could already
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen fail the query reliably. */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen len = mysql_real_escape_string(db->mysql, to, string, len);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void driver_mysql_exec(struct sql_db *_db, const char *query)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen mysql_prefix(db), query, mysql_error(db->mysql));
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void driver_mysql_query(struct sql_db *db, const char *query,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen sql_query_callback_t *callback, void *context)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic struct sql_result *
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainendriver_mysql_query_s(struct sql_db *_db, const char *query)
#ifdef CLIENT_MULTI_RESULTS
if (ret < 0 &&
int ret;
ret = 0;
return ret;
const char *field_name)
unsigned int idx)
unsigned long *lengths;
const char *field_name)
int idx;
if (idx < 0)
return NULL;
const char *errstr;
unsigned int idle_time;
int err;
return errstr;
static struct sql_transaction_context *
const char *error;
unsigned int *affected_rows_r)
int ret = 0;
return ret;
const char **error_r)
if (ret == 0) {
unsigned int *affected_rows)
void driver_mysql_init(void);
void driver_mysql_deinit(void);
void driver_mysql_init(void)
void driver_mysql_deinit(void)