driver-mysql.c revision 06b0c3be9905099038964b068216bbed155701de
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen, Alex Howansky */
06b0c3be9905099038964b068216bbed155701deTimo Sirainen/* Abort connect() if it can't connect within this time. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* Minimum delay between reconnecting to same server */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* Maximum time to avoiding reconnecting to same server */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* If no servers are connected but a query is requested, try reconnecting to
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen next server which has been disconnected longer than this (with a single
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen server setup this is really the "max delay" and the CONNECT_MAX_DELAY
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen is never used). */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const char *user, *password, *dbname, *unix_socket;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *ssl_cert, *ssl_key, *ssl_ca, *ssl_ca_path, *ssl_cipher;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen buffer_t *connections; /* struct mysql_connection[] */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenextern struct sql_result driver_mysql_error_result;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int driver_mysql_connect(struct mysql_connection *conn)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* don't try reconnecting more than once a second */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->last_connect + (time_t)conn->connect_delay > now)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (!conn->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen mysql_ssl_set(conn->mysql, db->ssl_key, db->ssl_cert,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "(remove ssl_ca and ssl_ca_path settings)");
06b0c3be9905099038964b068216bbed155701deTimo Sirainen failed = mysql_real_connect(conn->mysql, host, db->user, db->password,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* increase delay between reconnections to this
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_error("mysql: Connect failed to %s (%s): %s - "
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "waiting for %u seconds before retry",
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->ssl_set ? " using SSL" : "", db->dbname);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connect_all(struct mysql_db *db)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; i++)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connection_add(struct mysql_db *db, const char *host)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_append_space_unsafe(db->connections, sizeof(*conn));
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connection_free(struct mysql_connection *conn)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_parse_connect_string(struct mysql_db *db,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char **field;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen args = t_strsplit_spaces(connect_string, " ");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Missing value in connect string: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Unknown connect string: %s", name);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: No hosts given in connect string");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic struct sql_db *driver_mysql_init(const char *connect_string)
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen pool = pool_alloconly_create("mysql driver", 512);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_deinit(struct sql_db *_db)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; i++)
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainendriver_mysql_get_flags(struct sql_db *db __attr_unused__)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int driver_mysql_connection_do_query(struct mysql_connection *conn,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < 2; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* connection lost - try immediate reconnect */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* connected -> lost it -> connected -> lost again */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int driver_mysql_do_query(struct mysql_db *db, const char *query,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int i, start;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* go through the connections in round robin. if the connection
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen isn't available, try next one that is. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = driver_mysql_connection_do_query(&conn[i], query);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* success / failure */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* not connected, try next one */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen } while (i != start);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* none are connected. connect_delays may have gotten too high,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen reset all of them to see if some are still alive. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; i++)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_exec(struct sql_db *_db, const char *query)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen (void)driver_mysql_do_query(db, query, &conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_query(struct sql_db *_db, const char *query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback_t *callback, void *context)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen switch (driver_mysql_do_query(db, query, &conn)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* not connected */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* query ok */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.result = mysql_store_result(conn->mysql);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_next_row(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->row = mysql_fetch_row(result->result);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return mysql_errno(result->conn->mysql) ? -1 : 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_result_fetch_fields(struct mysql_result *result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields_count = mysql_num_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields = mysql_fetch_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic unsigned int
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_fields_count(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_name(struct sql_result *_result, unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_find_field(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strcmp(result->fields[i].name, field_name) == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_value(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_find_field_value(struct sql_result *result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen idx = driver_mysql_result_find_field(result, field_name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return driver_mysql_result_get_field_value(result, idx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *const *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_values(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic const char *driver_mysql_result_get_error(struct sql_result *_result)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_error_next_row(struct sql_result *result __attr_unused__)