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