bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen#include "ioloop.h"
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen#include "array.h"
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen#include "hex-binary.h"
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen#include "str.h"
009217abb57a24a4076092e8e4e165545747839eStephan Bosch#include "net.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "sql-api-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen#ifdef BUILD_MYSQL
06b0c3be9905099038964b068216bbed155701deTimo Sirainen#include <unistd.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <time.h>
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen#ifdef HAVE_ATTR_NULL
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen/* ugly way to tell clang that mysql.h is a system header and we don't want
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen to enable nonnull attributes for it by default.. */
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen# 4 "driver-mysql.c" 3
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen#endif
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <mysql.h>
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen#ifdef HAVE_ATTR_NULL
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen# 4 "driver-mysql.c" 3
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen# line 20
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen#endif
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <errmsg.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen#define MYSQL_DEFAULT_READ_TIMEOUT_SECS 30
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen#define MYSQL_DEFAULT_WRITE_TIMEOUT_SECS 30
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo 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;
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen int ssl_verify_server_cert;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen const char *option_file, *option_group;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch unsigned int client_flags;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen unsigned int connect_timeout, read_timeout, write_timeout;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen time_t last_success;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL *mysql;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int next_query_connection;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool 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
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool 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{
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen return db->host == NULL ? "mysql" :
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen 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;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen unsigned int secs_used;
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen time_t start_time;
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
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen if (db->host == NULL) {
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen /* assume option_file overrides the host, or if not we'll just
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen connect to localhost */
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen unix_socket = NULL;
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen host = NULL;
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen } else 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
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen mysql_options(db->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &db->connect_timeout);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen mysql_options(db->mysql, MYSQL_OPT_READ_TIMEOUT, &db->read_timeout);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen mysql_options(db->mysql, MYSQL_OPT_WRITE_TIMEOUT, &db->write_timeout);
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 );
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen#ifdef HAVE_MYSQL_SSL_VERIFY_SERVER_CERT
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen mysql_options(db->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
9abf4d9d5eeb74d70fc26deb024383cf87f276bcTimo Sirainen (void *)&db->ssl_verify_server_cert);
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen#endif
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
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 */
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen start_time = time(NULL);
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;
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen secs_used = time(NULL) - start_time;
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 {
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";
575fa28d92361c068b2c08d393605e1de661d922Martti Rannanjärvi db->ssl_verify_server_cert = 1;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen db->connect_timeout = SQL_CONNECT_TIMEOUT_SECS;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen db->read_timeout = MYSQL_DEFAULT_READ_TIMEOUT_SECS;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen db->write_timeout = MYSQL_DEFAULT_WRITE_TIMEOUT_SECS;
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;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch else if (strcmp(name, "port") == 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (net_str2port(value, &db->port) < 0)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch i_fatal("mysql: Invalid port number: %s", value);
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch } else if (strcmp(name, "client_flags") == 0) {
e180615c1db31c8a6f6a586ae40b1cfc2d6ee725Timo Sirainen if (str_to_uint(value, &db->client_flags) < 0)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch i_fatal("mysql: Invalid client flags: %s", value);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen } else if (strcmp(name, "connect_timeout") == 0) {
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (str_to_uint(value, &db->connect_timeout) < 0)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen i_fatal("mysql: Invalid read_timeout: %s", value);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen } else if (strcmp(name, "read_timeout") == 0) {
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (str_to_uint(value, &db->read_timeout) < 0)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen i_fatal("mysql: Invalid read_timeout: %s", value);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen } else if (strcmp(name, "write_timeout") == 0) {
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (str_to_uint(value, &db->write_timeout) < 0)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen i_fatal("mysql: Invalid read_timeout: %s", value);
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch } 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;
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen else if (strcmp(name, "ssl_verify_server_cert") == 0) {
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen if (strcmp(value, "yes") == 0)
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen db->ssl_verify_server_cert = 1;
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen else if (strcmp(value, "no") == 0)
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen db->ssl_verify_server_cert = 0;
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen else
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen i_fatal("mysql: Invalid boolean: %s", value);
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo 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
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen if (db->host == NULL && db->option_file == 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;
933de3f374e6971f50308cb7bea13a51a45287bfTimo Sirainen int err;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen
933de3f374e6971f50308cb7bea13a51a45287bfTimo Sirainen err = mysql_errno(db->mysql);
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen errstr = mysql_error(db->mysql);
933de3f374e6971f50308cb7bea13a51a45287bfTimo Sirainen if ((err == CR_SERVER_GONE_ERROR || err == CR_SERVER_LOST) &&
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{
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen struct sql_commit_result result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *error;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&result);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (sql_transaction_commit_s(&ctx, &error) < 0)
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen result.error = error;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen callback(&result, context);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic int ATTR_NULL(3)
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
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainenstatic const char *
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainendriver_mysql_escape_blob(struct sql_db *_db ATTR_UNUSED,
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen const unsigned char *data, size_t size)
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen{
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen string_t *str = t_str_new(128);
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen
dc5168232608d74ca56412044280ff0155ffe231Aki Tuomi str_append(str, "X'");
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen binary_to_hex_append(str, data, size);
dc5168232608d74ca56412044280ff0155ffe231Aki Tuomi str_append_c(str, '\'');
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen return str_c(str);
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen}
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo 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 = {
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .init = driver_mysql_init_v,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .deinit = driver_mysql_deinit_v,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .connect = driver_mysql_connect,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .disconnect = driver_mysql_disconnect,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .escape_string = driver_mysql_escape_string,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .exec = driver_mysql_exec,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .query = driver_mysql_query,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .query_s = driver_mysql_query_s,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_begin = driver_mysql_transaction_begin,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_commit = driver_mysql_transaction_commit,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_commit_s = driver_mysql_transaction_commit_s,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_rollback = driver_mysql_transaction_rollback,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .update = driver_mysql_update,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .escape_blob = driver_mysql_escape_blob,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainenconst struct sql_result driver_mysql_result = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .free = driver_mysql_result_free,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .next_row = driver_mysql_result_next_row,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_fields_count = driver_mysql_result_get_fields_count,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_field_name = driver_mysql_result_get_field_name,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .find_field = driver_mysql_result_find_field,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_field_value = driver_mysql_result_get_field_value,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_field_value_binary = driver_mysql_result_get_field_value_binary,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .find_field_value = driver_mysql_result_find_field_value,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_values = driver_mysql_result_get_values,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_error = 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 = {
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .free = driver_mysql_result_free,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .next_row = driver_mysql_result_error_next_row,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .get_error = driver_mysql_result_get_error,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen },
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen .failed_try_retry = TRUE
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *driver_mysql_version = DOVECOT_ABI_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