driver-mysql.c revision 6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817c
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek/* Copyright (c) 2003-2015 Dovecot authors, see the included COPYING file */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include "lib.h"
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include "ioloop.h"
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include "array.h"
d6d50c17e94dc0d3000345e8a933311c14bbb828Jakub Hrozek#include "hex-binary.h"
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek#include "str.h"
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include "net.h"
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include "sql-api-private.h"
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#ifdef BUILD_MYSQL
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek#include <unistd.h>
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek#include <time.h>
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek#ifdef HAVE_ATTR_NULL
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek/* ugly way to tell clang that mysql.h is a system header and we don't want
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek to enable nonnull attributes for it by default.. */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek# 4 "driver-mysql.c" 3
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include <mysql.h>
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#ifdef HAVE_ATTR_NULL
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek# 4 "driver-mysql.c" 3
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek# line 20
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#include <errmsg.h>
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#define MYSQL_DEFAULT_READ_TIMEOUT_SECS 30
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#define MYSQL_DEFAULT_WRITE_TIMEOUT_SECS 30
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstruct mysql_db {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct sql_db api;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek pool_t pool;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *user, *password, *dbname, *host, *unix_socket;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *ssl_cert, *ssl_key, *ssl_ca, *ssl_ca_path, *ssl_cipher;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek int ssl_verify_server_cert;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *option_file, *option_group;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek in_port_t port;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int client_flags;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int connect_timeout, read_timeout, write_timeout;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek time_t last_success;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek MYSQL *mysql;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int next_query_connection;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int ssl_set:1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstruct mysql_result {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct sql_result api;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek MYSQL_RES *result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek MYSQL_ROW row;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek MYSQL_FIELD *fields;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int fields_count;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek my_ulonglong affected_rows;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstruct mysql_transaction_context {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct sql_transaction_context ctx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek pool_t query_pool;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek const char *error;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int failed:1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekextern const struct sql_db driver_mysql_db;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekextern const struct sql_result driver_mysql_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekextern const struct sql_result driver_mysql_error_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const char *mysql_prefix(struct mysql_db *db)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return db->host == NULL ? "mysql" :
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek t_strdup_printf("mysql(%s)", db->host);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int driver_mysql_connect(struct sql_db *_db)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *unix_socket, *host;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek unsigned long client_flags = db->client_flags;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int secs_used;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek time_t start_time;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek bool failed;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_assert(db->api.state == SQL_DB_STATE_DISCONNECTED);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_db_set_state(&db->api, SQL_DB_STATE_CONNECTING);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (db->host == NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* assume option_file overrides the host, or if not we'll just
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek connect to localhost */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unix_socket = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek host = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else if (*db->host == '/') {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unix_socket = db->host;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek host = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unix_socket = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek host = db->host;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (db->option_file != NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_READ_DEFAULT_FILE,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->option_file);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &db->connect_timeout);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_OPT_READ_TIMEOUT, &db->read_timeout);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_OPT_WRITE_TIMEOUT, &db->write_timeout);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_READ_DEFAULT_GROUP,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->option_group != NULL ? db->option_group : "client");
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (!db->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#ifdef HAVE_MYSQL_SSL
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_ssl_set(db->mysql, db->ssl_key, db->ssl_cert,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->ssl_ca, db->ssl_ca_path
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#ifdef HAVE_MYSQL_SSL_CIPHER
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek , db->ssl_cipher
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek );
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#ifdef HAVE_MYSQL_SSL_VERIFY_SERVER_CERT
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_options(db->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (void *)&db->ssl_verify_server_cert);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek db->ssl_set = TRUE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#else
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_fatal("mysql: SSL support not compiled in "
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "(remove ssl_ca and ssl_ca_path settings)");
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek#ifdef CLIENT_MULTI_RESULTS
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek client_flags |= CLIENT_MULTI_RESULTS;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* CLIENT_MULTI_RESULTS allows the use of stored procedures */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek start_time = time(NULL);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek failed = mysql_real_connect(db->mysql, host, db->user, db->password,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->dbname, db->port, unix_socket,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek client_flags) == NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek secs_used = time(NULL) - start_time;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (failed) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* connecting could have taken a while. make sure that any
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek timeouts that get added soon will get a refreshed
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek timestamp. */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek io_loop_time_refresh();
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (db->api.connect_delay < secs_used)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->api.connect_delay = secs_used;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_error("%s: Connect failed to database (%s): %s - "
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "waiting for %u seconds before retry",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_prefix(db), db->dbname,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mysql_error(db->mysql), db->api.connect_delay);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->last_success = ioloop_time;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return 1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void driver_mysql_disconnect(struct sql_db *_db ATTR_UNUSED)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void driver_mysql_parse_connect_string(struct mysql_db *db,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *connect_string)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *const *args, *name, *value;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char **field;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->ssl_cipher = "HIGH";
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->ssl_verify_server_cert = 0; /* FIXME: change to 1 for v2.3 */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->connect_timeout = SQL_CONNECT_TIMEOUT_SECS;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->read_timeout = MYSQL_DEFAULT_READ_TIMEOUT_SECS;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->write_timeout = MYSQL_DEFAULT_WRITE_TIMEOUT_SECS;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek args = t_strsplit_spaces(connect_string, " ");
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek for (; *args != NULL; args++) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek value = strchr(*args, '=');
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (value == NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_fatal("mysql: Missing value in connect string: %s",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek *args);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek name = t_strdup_until(*args, value);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek value++;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek field = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (strcmp(name, "host") == 0 ||
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek strcmp(name, "hostaddr") == 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek field = &db->host;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek else if (strcmp(name, "user") == 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek field = &db->user;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek else if (strcmp(name, "password") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->password;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek else if (strcmp(name, "dbname") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->dbname;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "port") == 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (net_str2port(value, &db->port) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid port number: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "client_flags") == 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (str_to_uint(value, &db->client_flags) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid client flags: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "connect_timeout") == 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (str_to_uint(value, &db->connect_timeout) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid read_timeout: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "read_timeout") == 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (str_to_uint(value, &db->read_timeout) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid read_timeout: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "write_timeout") == 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (str_to_uint(value, &db->write_timeout) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid read_timeout: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "ssl_cert") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->ssl_cert;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "ssl_key") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->ssl_key;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "ssl_ca") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->ssl_ca;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "ssl_ca_path") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->ssl_ca_path;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "ssl_cipher") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->ssl_cipher;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "ssl_verify_server_cert") == 0) {
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek if (strcmp(value, "yes") == 0)
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek db->ssl_verify_server_cert = 1;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek else if (strcmp(value, "no") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek db->ssl_verify_server_cert = 0;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek else
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Invalid boolean: %s", value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } else if (strcmp(name, "option_file") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->option_file;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(name, "option_group") == 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek field = &db->option_group;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: Unknown connect string: %s", name);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (field != NULL)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek *field = p_strdup(db->pool, value);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (db->host == NULL && db->option_file == NULL)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql: No hosts given in connect string");
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek db->mysql = mysql_init(NULL);
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek if (db->mysql == NULL)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_fatal("mysql_init() failed");
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic struct sql_db *driver_mysql_init_v(const char *connect_string)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct mysql_db *db;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek pool_t pool;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek pool = pool_alloconly_create("mysql driver", 1024);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek db = p_new(pool, struct mysql_db, 1);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek db->pool = pool;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek db->api = driver_mysql_db;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek T_BEGIN {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek driver_mysql_parse_connect_string(db, connect_string);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek } T_END;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return &db->api;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic void driver_mysql_deinit_v(struct sql_db *_db)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct mysql_db *db = (struct mysql_db *)_db;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek _db->no_reconnect = TRUE;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek mysql_close(db->mysql);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek array_free(&_db->module_contexts);
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek pool_unref(&db->pool);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic int driver_mysql_do_query(struct mysql_db *db, const char *query)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (mysql_query(db->mysql, query) == 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return 0;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* failed */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek switch (mysql_errno(db->mysql)) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek case CR_SERVER_GONE_ERROR:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek case CR_SERVER_LOST:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek default:
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek break;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic const char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_escape_string(struct sql_db *_db, const char *string)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek size_t len = strlen(string);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek char *to;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (_db->state == SQL_DB_STATE_DISCONNECTED) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* try connecting */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (void)sql_connect(&db->api);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (db->mysql == NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* FIXME: we don't have a valid connection, so fallback
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek to using default escaping. the next query will most
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek likely fail anyway so it shouldn't matter that much
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek what we return here.. Anyway, this API needs
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek changing so that the escaping function could already
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek fail the query reliably. */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek to = t_buffer_get(len * 2 + 1);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek len = mysql_escape_string(to, string, len);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek t_buffer_alloc(len + 1);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return to;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek to = t_buffer_get(len * 2 + 1);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek len = mysql_real_escape_string(db->mysql, to, string, len);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek t_buffer_alloc(len + 1);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return to;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void driver_mysql_exec(struct sql_db *_db, const char *query)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (driver_mysql_do_query(db, query) < 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_error("%s: Query '%s' failed: %s",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek mysql_prefix(db), query, mysql_error(db->mysql));
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void driver_mysql_query(struct sql_db *db, const char *query,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_query_callback_t *callback, void *context)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct sql_result *result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result = sql_query_s(db, query);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->callback = TRUE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek callback(result, context);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek result->callback = FALSE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_result_unref(result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic struct sql_result *
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekdriver_mysql_query_s(struct sql_db *_db, const char *query)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek int ret;
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek result = i_new(struct mysql_result, 1);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->api = driver_mysql_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (driver_mysql_do_query(db, query) < 0)
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek result->api = driver_mysql_error_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek else {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* query ok */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->affected_rows = mysql_affected_rows(db->mysql);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->result = mysql_store_result(db->mysql);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek#ifdef CLIENT_MULTI_RESULTS
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* Because we've enabled CLIENT_MULTI_RESULTS, we need to read
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (ignore) extra results - there should not be any.
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret is: -1 = done, >0 = error, 0 = more results. */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek while ((ret = mysql_next_result(db->mysql)) == 0) ;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek#else
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret = -1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (ret < 0 &&
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (result->result != NULL || mysql_errno(db->mysql) == 0)) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* ok */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* failed */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (result->result != NULL)
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek mysql_free_result(result->result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->api = driver_mysql_error_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek result->api.db = _db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->api.refcount = 1;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return &result->api;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek}
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void driver_mysql_result_free(struct sql_result *_result)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek{
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek i_assert(_result != &sql_not_connected_result);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (_result->callback)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek if (result->result != NULL)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek mysql_free_result(result->result);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek i_free(result);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek}
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozekstatic int driver_mysql_result_next_row(struct sql_result *_result)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek{
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_result->db;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek int ret;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (result->result == NULL) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* no results */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return 0;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek }
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek result->row = mysql_fetch_row(result->result);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (result->row != NULL)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ret = 1;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek else {
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek if (mysql_errno(db->mysql) != 0)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return -1;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ret = 0;
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek }
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek db->last_success = ioloop_time;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return ret;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek}
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void driver_mysql_result_fetch_fields(struct mysql_result *result)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek{
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (result->fields != NULL)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek result->fields_count = mysql_num_fields(result->result);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek result->fields = mysql_fetch_fields(result->result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic unsigned int
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_get_fields_count(struct sql_result *_result)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_fetch_fields(result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return result->fields_count;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic const char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_get_field_name(struct sql_result *_result, unsigned int idx)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_fetch_fields(result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_assert(idx < result->fields_count);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return result->fields[idx].name;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int driver_mysql_result_find_field(struct sql_result *_result,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *field_name)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int i;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_fetch_fields(result);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek for (i = 0; i < result->fields_count; i++) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (strcmp(result->fields[i].name, field_name) == 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return i;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic const char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_get_field_value(struct sql_result *_result,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int idx)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return (const char *)result->row[idx];
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const unsigned char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_get_field_value_binary(struct sql_result *_result,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int idx, size_t *size_r)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned long *lengths;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek lengths = mysql_fetch_lengths(result->result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek *size_r = lengths[idx];
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return (const void *)result->row[idx];
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_find_field_value(struct sql_result *result,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *field_name)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek int idx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek idx = driver_mysql_result_find_field(result, field_name);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (idx < 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return driver_mysql_result_get_field_value(result, idx);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const char *const *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_get_values(struct sql_result *_result)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return (const char *const *)result->row;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const char *driver_mysql_result_get_error(struct sql_result *_result)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_result->db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *errstr;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int idle_time;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek int err;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek err = mysql_errno(db->mysql);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek errstr = mysql_error(db->mysql);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if ((err == CR_SERVER_GONE_ERROR || err == CR_SERVER_LOST) &&
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek db->last_success != 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek idle_time = ioloop_time - db->last_success;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek errstr = t_strdup_printf("%s (idled for %u secs)",
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek errstr, idle_time);
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return errstr;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic struct sql_transaction_context *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_transaction_begin(struct sql_db *db)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_transaction_context *ctx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx = i_new(struct mysql_transaction_context, 1);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->ctx.db = db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->query_pool = pool_alloconly_create("mysql transaction", 1024);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return &ctx->ctx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_transaction_commit(struct sql_transaction_context *ctx,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek sql_commit_callback_t *callback, void *context)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char *error;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (sql_transaction_commit_s(&ctx, &error) < 0)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek callback(error, context);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek else
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek callback(NULL, context);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int ATTR_NULL(3)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozektransaction_send_query(struct mysql_transaction_context *ctx, const char *query,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek unsigned int *affected_rows_r)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct sql_result *_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek int ret = 0;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (ctx->failed)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek _result = sql_query_s(ctx->ctx.db, query);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (sql_result_next_row(_result) < 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->error = sql_result_get_error(_result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->failed = TRUE;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek ret = -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else if (affected_rows_r != NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_result *result = (struct mysql_result *)_result;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_assert(result->affected_rows != (my_ulonglong)-1);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek *affected_rows_r = result->affected_rows;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_result_unref(_result);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return ret;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int driver_mysql_try_commit_s(struct mysql_transaction_context *ctx)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct sql_transaction_context *_ctx = &ctx->ctx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* try to use a transaction in any case,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek even if it's not actually functional. */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (transaction_send_query(ctx, "BEGIN", NULL) < 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (_ctx->db->state != SQL_DB_STATE_DISCONNECTED)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* we got disconnected, retry */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return 0;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek while (_ctx->head != NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (transaction_send_query(ctx, _ctx->head->query,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek _ctx->head->affected_rows) < 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek _ctx->head = _ctx->head->next;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (transaction_send_query(ctx, "COMMIT", NULL) < 0)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return 1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozekstatic int
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozekdriver_mysql_transaction_commit_s(struct sql_transaction_context *_ctx,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek const char **error_r)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_transaction_context *ctx =
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (struct mysql_transaction_context *)_ctx;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek struct mysql_db *db = (struct mysql_db *)_ctx->db;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek int ret = 1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek *error_r = NULL;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek if (_ctx->head != NULL) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret = driver_mysql_try_commit_s(ctx);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek *error_r = t_strdup(ctx->error);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (ret == 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek i_info("%s: Disconnected from database, "
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "retrying commit", db->dbname);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (sql_connect(_ctx->db) >= 0) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->failed = FALSE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret = driver_mysql_try_commit_s(ctx);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek sql_transaction_rollback(&_ctx);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return ret <= 0 ? -1 : 0;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic void
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekdriver_mysql_transaction_rollback(struct sql_transaction_context *_ctx)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct mysql_transaction_context *ctx =
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek (struct mysql_transaction_context *)_ctx;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek pool_unref(&ctx->query_pool);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_free(ctx);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_update(struct sql_transaction_context *_ctx, const char *query,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek unsigned int *affected_rows)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek struct mysql_transaction_context *ctx =
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (struct mysql_transaction_context *)_ctx;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_transaction_add_query(&ctx->ctx, ctx->query_pool,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek query, affected_rows);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic const char *
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_escape_blob(struct sql_db *_db ATTR_UNUSED,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek const unsigned char *data, size_t size)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek string_t *str = t_str_new(128);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek str_append(str, "HEX('");
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek binary_to_hex_append(str, data, size);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek str_append_c(str, ')');
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return str_c(str);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekconst struct sql_db driver_mysql_db = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek .name = "mysql",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek .flags = SQL_DB_FLAG_BLOCKING | SQL_DB_FLAG_POOLED,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek .v = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_init_v,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_deinit_v,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek driver_mysql_connect,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_disconnect,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_escape_string,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_exec,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_query,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_query_s,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_transaction_begin,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek driver_mysql_transaction_commit,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_transaction_commit_s,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_transaction_rollback,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_update,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_escape_blob
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekconst struct sql_result driver_mysql_result = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek .v = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_free,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_next_row,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_fields_count,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_field_name,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_find_field,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_field_value,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_field_value_binary,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek driver_mysql_result_find_field_value,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_values,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_error
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekdriver_mysql_result_error_next_row(struct sql_result *result ATTR_UNUSED)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return -1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekconst struct sql_result driver_mysql_error_result = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek .v = {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_free,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_error_next_row,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek driver_mysql_result_get_error
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek },
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek .failed_try_retry = TRUE
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek};
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekconst char *driver_mysql_version = DOVECOT_ABI_VERSION;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekvoid driver_mysql_init(void);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekvoid driver_mysql_deinit(void);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekvoid driver_mysql_init(void)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_driver_register(&driver_mysql_db);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekvoid driver_mysql_deinit(void)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek{
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek sql_driver_unregister(&driver_mysql_db);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek#endif
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek