driver-mysql.c revision 3ec16f23d3c94c225e5b74d84c6a69064922cd9d
183bea41fa640dc8117f3eb45ff935cd81377a84Timo Sirainen/* Copyright (c) 2003-2011 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen#include "ioloop.h"
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen#include "array.h"
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen#include "str.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "sql-api-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen#ifdef BUILD_MYSQL
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <stdlib.h>
06b0c3be9905099038964b068216bbed155701deTimo Sirainen#include <unistd.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <time.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <mysql.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <errmsg.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mysql_db {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct sql_db api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_t pool;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const char *user, *password, *dbname, *host, *unix_socket;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *ssl_cert, *ssl_key, *ssl_ca, *ssl_ca_path, *ssl_cipher;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen const char *option_file, *option_group;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int port, client_flags;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen time_t last_success;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL *mysql;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int next_query_connection;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int ssl_set:1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mysql_result {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct sql_result api;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL_RES *result;
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen MYSQL_ROW row;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL_FIELD *fields;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int fields_count;
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen my_ulonglong affected_rows;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstruct mysql_transaction_context {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct sql_transaction_context ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pool_t query_pool;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const char *error;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen unsigned int failed:1;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen};
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenextern const struct sql_db driver_mysql_db;
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenextern const struct sql_result driver_mysql_result;
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenextern const struct sql_result driver_mysql_error_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainenstatic const char *mysql_prefix(struct mysql_db *db)
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen{
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen return t_strdup_printf("mysql(%s)", db->host);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen}
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int driver_mysql_connect(struct sql_db *_db)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *unix_socket, *host;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen unsigned long client_flags = db->client_flags;
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen unsigned int secs_used;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool failed;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(db->api.state == SQL_DB_STATE_DISCONNECTED);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_CONNECTING);
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (*db->host == '/') {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unix_socket = db->host;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen host = NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unix_socket = NULL;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen host = db->host;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen if (db->option_file != NULL) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mysql_options(db->mysql, MYSQL_READ_DEFAULT_FILE,
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen db->option_file);
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen }
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mysql_options(db->mysql, MYSQL_READ_DEFAULT_GROUP,
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen db->option_group != NULL ? db->option_group : "client");
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (!db->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#ifdef HAVE_MYSQL_SSL
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mysql_ssl_set(db->mysql, db->ssl_key, db->ssl_cert,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen db->ssl_ca, db->ssl_ca_path
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#ifdef HAVE_MYSQL_SSL_CIPHER
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen , db->ssl_cipher
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#endif
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen );
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen db->ssl_set = TRUE;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#else
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: SSL support not compiled in "
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "(remove ssl_ca and ssl_ca_path settings)");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#endif
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen alarm(SQL_CONNECT_TIMEOUT_SECS);
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen#ifdef CLIENT_MULTI_RESULTS
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen client_flags |= CLIENT_MULTI_RESULTS;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen#endif
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen /* CLIENT_MULTI_RESULTS allows the use of stored procedures */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen failed = mysql_real_connect(db->mysql, host, db->user, db->password,
06b0c3be9905099038964b068216bbed155701deTimo Sirainen db->dbname, db->port, unix_socket,
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen client_flags) == NULL;
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen secs_used = SQL_CONNECT_TIMEOUT_SECS - alarm(0);
06b0c3be9905099038964b068216bbed155701deTimo Sirainen if (failed) {
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen /* connecting could have taken a while. make sure that any
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen timeouts that get added soon will get a refreshed
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen timestamp. */
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen io_loop_time_refresh();
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen if (db->api.connect_delay < secs_used)
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen db->api.connect_delay = secs_used;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_error("%s: Connect failed to database (%s): %s - "
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "waiting for %u seconds before retry",
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen mysql_prefix(db), db->dbname,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mysql_error(db->mysql), db->api.connect_delay);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_info("%s: Connected to database %s%s", mysql_prefix(db),
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen db->dbname, db->ssl_set ? " using SSL" : "");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen db->last_success = ioloop_time;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 1;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic void driver_mysql_disconnect(struct sql_db *_db ATTR_UNUSED)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_parse_connect_string(struct mysql_db *db,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *connect_string)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *const *args, *name, *value;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char **field;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->ssl_cipher = "HIGH";
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen args = t_strsplit_spaces(connect_string, " ");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (; *args != NULL; args++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen value = strchr(*args, '=');
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (value == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Missing value in connect string: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *args);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name = t_strdup_until(*args, value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen value++;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = NULL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (strcmp(name, "host") == 0 ||
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen strcmp(name, "hostaddr") == 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen field = &db->host;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "user") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->user;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "password") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->password;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "dbname") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->dbname;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "port") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->port = atoi(value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "client_flags") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->client_flags = atoi(value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_cert") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_cert;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_key") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_key;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_ca") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_ca;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_ca_path") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_ca_path;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_cipher") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_cipher;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen else if (strcmp(name, "option_file") == 0)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen field = &db->option_file;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen else if (strcmp(name, "option_group") == 0)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen field = &db->option_group;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Unknown connect string: %s", name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (field != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *field = p_strdup(db->pool, value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (db->host == NULL)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: No hosts given in connect string");
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen db->mysql = mysql_init(NULL);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (db->mysql == NULL)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_fatal("mysql_init() failed");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic struct sql_db *driver_mysql_init_v(const char *connect_string)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen pool_t pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
bc27fcd011f86208feaf73da9778a66ac7d7d3abTimo Sirainen pool = pool_alloconly_create("mysql driver", 1024);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen db = p_new(pool, struct mysql_db, 1);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen db->pool = pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->api = driver_mysql_db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return &db->api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void driver_mysql_deinit_v(struct sql_db *_db)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainen _db->no_reconnect = TRUE;
9222c96ab9f42b25d5d5260f9e7a42c694715b0aTimo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
9222c96ab9f42b25d5d5260f9e7a42c694715b0aTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mysql_close(db->mysql);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen array_free(&_db->module_contexts);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&db->pool);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int driver_mysql_do_query(struct mysql_db *db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (mysql_query(db->mysql, query) == 0)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen return 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* failed */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen switch (mysql_errno(db->mysql)) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen case CR_SERVER_GONE_ERROR:
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen case CR_SERVER_LOST:
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen break;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen default:
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen break;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen return -1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
13a8c553f293349248b161ff851743498916e26eTimo Sirainenstatic const char *
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainendriver_mysql_escape_string(struct sql_db *_db, const char *string)
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen{
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen size_t len = strlen(string);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen char *to;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (_db->state == SQL_DB_STATE_DISCONNECTED) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* try connecting */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen (void)sql_connect(&db->api);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (db->mysql == NULL) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* FIXME: we don't have a valid connection, so fallback
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen to using default escaping. the next query will most
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen likely fail anyway so it shouldn't matter that much
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen what we return here.. Anyway, this API needs
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen changing so that the escaping function could already
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen fail the query reliably. */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen to = t_buffer_get(len * 2 + 1);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen len = mysql_escape_string(to, string, len);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen t_buffer_alloc(len + 1);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return to;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen to = t_buffer_get(len * 2 + 1);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen len = mysql_real_escape_string(db->mysql, to, string, len);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen t_buffer_alloc(len + 1);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return to;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen}
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_exec(struct sql_db *_db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3db8062598ce08e9320c84f77c267b9c70cb0809Timo Sirainen if (driver_mysql_do_query(db, query) < 0) {
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_error("%s: Query '%s' failed: %s",
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen mysql_prefix(db), query, mysql_error(db->mysql));
3db8062598ce08e9320c84f77c267b9c70cb0809Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void driver_mysql_query(struct sql_db *db, const char *query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback_t *callback, void *context)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct sql_result *result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result = sql_query_s(db, query);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->callback = TRUE;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(result, context);
eeea0a402bcd9533e9e359f2a2518e3216162151Timo Sirainen result->callback = FALSE;
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen sql_result_unref(result);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic struct sql_result *
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_query_s(struct sql_db *_db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_result *result;
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen int ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result = i_new(struct mysql_result, 1);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->api = driver_mysql_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen if (driver_mysql_do_query(db, query) < 0)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen result->api = driver_mysql_error_result;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* query ok */
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen result->affected_rows = mysql_affected_rows(db->mysql);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen result->result = mysql_store_result(db->mysql);
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen#ifdef CLIENT_MULTI_RESULTS
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen /* Because we've enabled CLIENT_MULTI_RESULTS, we need to read
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen (ignore) extra results - there should not be any.
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen ret is: -1 = done, >0 = error, 0 = more results. */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen while ((ret = mysql_next_result(db->mysql)) == 0) ;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen#else
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen ret = -1;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen#endif
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen if (ret < 0 &&
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen (result->result != NULL || mysql_errno(db->mysql) == 0)) {
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen /* ok */
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen } else {
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen /* failed */
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen if (result->result != NULL)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen mysql_free_result(result->result);
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen result->api = driver_mysql_error_result;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a74e4a66db99a69cca71d7c5ac1feae46d92138fTimo Sirainen result->api.db = _db;
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen result->api.refcount = 1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return &result->api;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void driver_mysql_result_free(struct sql_result *_result)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen i_assert(_result != &sql_not_connected_result);
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen if (_result->callback)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (result->result != NULL)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mysql_free_result(result->result);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_next_row(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mysql_db *db = (struct mysql_db *)_result->db;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen int ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen if (result->result == NULL) {
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen /* no results */
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen return 0;
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen }
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->row = mysql_fetch_row(result->result);
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen if (result->row != NULL)
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen ret = 1;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen else {
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen if (mysql_errno(db->mysql) != 0)
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen return -1;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen ret = 0;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen }
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen db->last_success = ioloop_time;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_result_fetch_fields(struct mysql_result *result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (result->fields != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields_count = mysql_num_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields = mysql_fetch_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic unsigned int
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_fields_count(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return result->fields_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_name(struct sql_result *_result, unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(idx < result->fields_count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return result->fields[idx].name;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_find_field(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *field_name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < result->fields_count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strcmp(result->fields[i].name, field_name) == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_value(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return (const char *)result->row[idx];
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic const unsigned char *
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainendriver_mysql_result_get_field_value_binary(struct sql_result *_result,
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen unsigned int idx, size_t *size_r)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen{
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen unsigned long *lengths;
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen lengths = mysql_fetch_lengths(result->result);
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen *size_r = lengths[idx];
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen return (const void *)result->row[idx];
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_find_field_value(struct sql_result *result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *field_name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen idx = driver_mysql_result_find_field(result, field_name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (idx < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return driver_mysql_result_get_field_value(result, idx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *const *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_values(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return (const char *const *)result->row;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic const char *driver_mysql_result_get_error(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mysql_db *db = (struct mysql_db *)_result->db;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen const char *errstr;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen unsigned int idle_time;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen errstr = mysql_error(db->mysql);
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen if (mysql_errno(db->mysql) == CR_SERVER_GONE_ERROR &&
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen db->last_success != 0) {
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen idle_time = ioloop_time - db->last_success;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen errstr = t_strdup_printf("%s (idled for %u secs)",
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen errstr, idle_time);
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen }
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen return errstr;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic struct sql_transaction_context *
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_begin(struct sql_db *db)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx = i_new(struct mysql_transaction_context, 1);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx->ctx.db = db;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->query_pool = pool_alloconly_create("mysql transaction", 1024);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return &ctx->ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_commit(struct sql_transaction_context *ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen sql_commit_callback_t *callback, void *context)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *error;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (sql_transaction_commit_s(&ctx, &error) < 0)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(error, context);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen else
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(NULL, context);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
59811ccfeb7dccc51e3be50c299c2ed853a1e2f3Timo Sirainenstatic int
59811ccfeb7dccc51e3be50c299c2ed853a1e2f3Timo Sirainentransaction_send_query(struct mysql_transaction_context *ctx, const char *query,
59811ccfeb7dccc51e3be50c299c2ed853a1e2f3Timo Sirainen unsigned int *affected_rows_r)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen{
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen struct sql_result *_result;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen int ret = 0;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (ctx->failed)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return -1;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen _result = sql_query_s(ctx->ctx.db, query);
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen if (sql_result_next_row(_result) < 0) {
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen ctx->error = sql_result_get_error(_result);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->failed = TRUE;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = -1;
59811ccfeb7dccc51e3be50c299c2ed853a1e2f3Timo Sirainen } else if (affected_rows_r != NULL) {
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen i_assert(result->affected_rows != (my_ulonglong)-1);
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen *affected_rows_r = result->affected_rows;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen sql_result_unref(_result);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return ret;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen}
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainenstatic int driver_mysql_try_commit_s(struct mysql_transaction_context *ctx)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen{
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen struct sql_transaction_context *_ctx = &ctx->ctx;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen /* try to use a transaction in any case,
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen even if it's not actually functional. */
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (transaction_send_query(ctx, "BEGIN", NULL) < 0) {
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (_ctx->db->state != SQL_DB_STATE_DISCONNECTED)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return -1;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen /* we got disconnected, retry */
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return 0;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen }
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen while (_ctx->head != NULL) {
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (transaction_send_query(ctx, _ctx->head->query,
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen _ctx->head->affected_rows) < 0)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return -1;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen _ctx->head = _ctx->head->next;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen }
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (transaction_send_query(ctx, "COMMIT", NULL) < 0)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return -1;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return 1;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen}
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic int
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_commit_s(struct sql_transaction_context *_ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char **error_r)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen struct mysql_db *db = (struct mysql_db *)_ctx->db;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen int ret = 1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *error_r = NULL;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (_ctx->head != NULL) {
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen ret = driver_mysql_try_commit_s(ctx);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen *error_r = t_strdup(ctx->error);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (ret == 0) {
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen i_info("%s: Disconnected from database, "
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen "retrying commit", db->dbname);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (sql_connect(_ctx->db) >= 0) {
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen ctx->failed = FALSE;
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen ret = driver_mysql_try_commit_s(ctx);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sql_transaction_rollback(&_ctx);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return ret <= 0 ? -1 : 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_rollback(struct sql_transaction_context *_ctx)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&ctx->query_pool);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(ctx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainendriver_mysql_update(struct sql_transaction_context *_ctx, const char *query,
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen unsigned int *affected_rows)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen sql_transaction_add_query(&ctx->ctx, ctx->query_pool,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen query, affected_rows);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenconst struct sql_db driver_mysql_db = {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen .name = "mysql",
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen .flags = SQL_DB_FLAG_BLOCKING | SQL_DB_FLAG_POOLED,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_init_v,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_deinit_v,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen driver_mysql_connect,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen driver_mysql_disconnect,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_escape_string,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_exec,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_query,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_query_s,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_begin,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_commit,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_commit_s,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_rollback,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_update
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenconst struct sql_result driver_mysql_result = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_free,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_next_row,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_fields_count,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_name,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_find_field,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_value,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_value_binary,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_find_field_value,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_values,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_error
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendriver_mysql_result_error_next_row(struct sql_result *result ATTR_UNUSED)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenconst struct sql_result driver_mysql_error_result = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_free,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_error_next_row,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_error
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen },
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen .failed_try_retry = TRUE
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
4371df92c07fb923aabca7e90d307eccac48b2d6Timo Sirainenconst char *driver_mysql_version = DOVECOT_VERSION;
4371df92c07fb923aabca7e90d307eccac48b2d6Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_init(void);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_deinit(void);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_init(void)
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen{
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sql_driver_register(&driver_mysql_db);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen}
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_deinit(void)
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen{
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sql_driver_unregister(&driver_mysql_db);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen}
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#endif