driver-mysql.c revision bc27fcd011f86208feaf73da9778a66ac7d7d3ab
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen#include "array.h"
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen#include "str.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "sql-api-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen#ifdef BUILD_MYSQL
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <stdlib.h>
06b0c3be9905099038964b068216bbed155701deTimo Sirainen#include <unistd.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <time.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <mysql.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <errmsg.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
06b0c3be9905099038964b068216bbed155701deTimo Sirainen/* Abort connect() if it can't connect within this time. */
06b0c3be9905099038964b068216bbed155701deTimo Sirainen#define MYSQL_CONNECT_FAILURE_TIMEOUT 10
06b0c3be9905099038964b068216bbed155701deTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* Minimum delay between reconnecting to same server */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#define CONNECT_MIN_DELAY 1
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* Maximum time to avoiding reconnecting to same server */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#define CONNECT_MAX_DELAY (60*30)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen/* If no servers are connected but a query is requested, try reconnecting to
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen next server which has been disconnected longer than this (with a single
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen server setup this is really the "max delay" and the CONNECT_MAX_DELAY
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen is never used). */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#define CONNECT_RESET_DELAY 15
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mysql_db {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct sql_db api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_t pool;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const char *user, *password, *dbname, *unix_socket;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *ssl_cert, *ssl_key, *ssl_ca, *ssl_ca_path, *ssl_cipher;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen const char *option_file, *option_group;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int port, client_flags;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_DEFINE(connections, struct mysql_connection);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int next_query_connection;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen};
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstruct mysql_connection {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_db *db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL *mysql;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const char *host;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int connect_delay;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int connect_failure_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen time_t last_connect;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int connected:1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int ssl_set:1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mysql_result {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct sql_result api;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL_RES *result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL_ROW row;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MYSQL_FIELD *fields;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int fields_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstruct mysql_transaction_context {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct sql_transaction_context ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen pool_t query_pool;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen struct mysql_query_list *head, *tail;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const char *error;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen unsigned int failed:1;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen};
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainenstruct mysql_query_list {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen struct mysql_query_list *next;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const char *query;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen unsigned int *affected_rows;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen};
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenextern struct sql_db driver_mysql_db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenextern struct sql_result driver_mysql_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenextern struct sql_result driver_mysql_error_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool driver_mysql_connect(struct mysql_connection *conn)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_db *db = conn->db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *unix_socket, *host;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen time_t now;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool failed;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->connected)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* don't try reconnecting more than once a second */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen now = time(NULL);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->last_connect + (time_t)conn->connect_delay > now)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return FALSE;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->last_connect = now;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (*conn->host == '/') {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unix_socket = conn->host;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen host = NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unix_socket = NULL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen host = conn->host;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen if (db->option_file != NULL) {
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen mysql_options(conn->mysql, MYSQL_READ_DEFAULT_FILE,
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen db->option_file);
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen }
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen mysql_options(conn->mysql, MYSQL_READ_DEFAULT_GROUP,
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen db->option_group != NULL ? db->option_group : "client");
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (!conn->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#ifdef HAVE_MYSQL_SSL
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen mysql_ssl_set(conn->mysql, db->ssl_key, db->ssl_cert,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen db->ssl_ca, db->ssl_ca_path
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#ifdef HAVE_MYSQL_SSL_CIPHER
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen , db->ssl_cipher
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#endif
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen );
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->ssl_set = TRUE;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#else
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: SSL support not compiled in "
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "(remove ssl_ca and ssl_ca_path settings)");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#endif
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
06b0c3be9905099038964b068216bbed155701deTimo Sirainen alarm(MYSQL_CONNECT_FAILURE_TIMEOUT);
06b0c3be9905099038964b068216bbed155701deTimo Sirainen failed = mysql_real_connect(conn->mysql, host, db->user, db->password,
06b0c3be9905099038964b068216bbed155701deTimo Sirainen db->dbname, db->port, unix_socket,
06b0c3be9905099038964b068216bbed155701deTimo Sirainen db->client_flags) == NULL;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen alarm(0);
06b0c3be9905099038964b068216bbed155701deTimo Sirainen if (failed) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->connect_failure_count > 0) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* increase delay between reconnections to this
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen server */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_delay *= 5;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->connect_delay > CONNECT_MAX_DELAY)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_delay = CONNECT_MAX_DELAY;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_failure_count++;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_error("mysql: Connect failed to %s (%s): %s - "
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen "waiting for %u seconds before retry",
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen host != NULL ? host : unix_socket, db->dbname,
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen mysql_error(conn->mysql), conn->connect_delay);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen i_info("mysql: Connected to %s%s (%s)",
200bedfb0a0472b74b2ec50c0a36bb167f39ea76Timo Sirainen host != NULL ? host : unix_socket,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->ssl_set ? " using SSL" : "", db->dbname);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_failure_count = 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_delay = CONNECT_MIN_DELAY;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connected = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainenstatic int driver_mysql_connect_all(struct sql_db *_db)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen int ret = -1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen array_foreach_modifiable(&db->connections, conn) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen if (driver_mysql_connect(conn))
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen ret = 1;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen }
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connection_add(struct mysql_db *db, const char *host)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen conn = array_append_space(&db->connections);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->db = db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->host = p_strdup(db->pool, host);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->mysql = mysql_init(NULL);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (conn->mysql == NULL)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql_init() failed");
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_delay = CONNECT_MIN_DELAY;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connection_free(struct mysql_connection *conn)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen mysql_close(conn->mysql);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_parse_connect_string(struct mysql_db *db,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *connect_string)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *const *args, *name, *value;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char **field;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->ssl_cipher = "HIGH";
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen args = t_strsplit_spaces(connect_string, " ");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (; *args != NULL; args++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen value = strchr(*args, '=');
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (value == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Missing value in connect string: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *args);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name = t_strdup_until(*args, value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen value++;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = NULL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (strcmp(name, "host") == 0 ||
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen strcmp(name, "hostaddr") == 0)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen driver_mysql_connection_add(db, value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "user") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->user;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "password") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->password;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "dbname") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->dbname;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "port") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->port = atoi(value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "client_flags") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->client_flags = atoi(value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_cert") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_cert;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_key") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_key;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_ca") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_ca;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_ca_path") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_ca_path;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else if (strcmp(name, "ssl_cipher") == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen field = &db->ssl_cipher;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen else if (strcmp(name, "option_file") == 0)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen field = &db->option_file;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen else if (strcmp(name, "option_group") == 0)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen field = &db->option_group;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("mysql: Unknown connect string: %s", name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (field != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *field = p_strdup(db->pool, value);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen if (array_count(&db->connections) == 0)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: No hosts given in connect string");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic struct sql_db *driver_mysql_init_v(const char *connect_string)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen pool_t pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
bc27fcd011f86208feaf73da9778a66ac7d7d3abTimo Sirainen pool = pool_alloconly_create("mysql driver", 1024);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen db = p_new(pool, struct mysql_db, 1);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen db->pool = pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->api = driver_mysql_db;
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen p_array_init(&db->connections, db->pool, 6);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return &db->api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void driver_mysql_deinit_v(struct sql_db *_db)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen array_foreach_modifiable(&db->connections, conn)
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen (void)driver_mysql_connection_free(conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen array_free(&_db->module_contexts);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&db->pool);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainenstatic enum sql_db_flags
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendriver_mysql_get_flags(struct sql_db *db ATTR_UNUSED)
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen{
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen return SQL_DB_FLAG_BLOCKING;
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen}
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int driver_mysql_connection_do_query(struct mysql_connection *conn,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < 2; i++) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (!driver_mysql_connect(conn))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (mysql_query(conn->mysql, query) == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* failed */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen switch (mysql_errno(conn->mysql)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case CR_SERVER_GONE_ERROR:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case CR_SERVER_LOST:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* connection lost - try immediate reconnect */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connected = FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen default:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* connected -> lost it -> connected -> lost again */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int driver_mysql_do_query(struct mysql_db *db, const char *query,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection **conn_r)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen unsigned int i, start, count;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool reset;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen conn = array_get_modifiable(&db->connections, &count);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* go through the connections in round robin. if the connection
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen isn't available, try next one that is. */
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen start = db->next_query_connection % count;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen db->next_query_connection++;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen for (reset = FALSE;; reset = TRUE) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i = start;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen do {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ret = driver_mysql_connection_do_query(&conn[i], query);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (ret != 0) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* success / failure */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen *conn_r = &conn[i];
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* not connected, try next one */
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen i = (i + 1) % count;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen } while (i != start);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (reset)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen break;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* none are connected. connect_delays may have gotten too high,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen reset all of them to see if some are still alive. */
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen for (i = 0; i < count; i++)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn[i].connect_delay = CONNECT_RESET_DELAY;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
0546f051db6f510aa84d8c748cb46e584d3fcdfbTimo Sirainen *conn_r = NULL;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
13a8c553f293349248b161ff851743498916e26eTimo Sirainenstatic const char *
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainendriver_mysql_escape_string(struct sql_db *_db, const char *string)
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen{
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen struct mysql_connection *conn;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen unsigned int i, count;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen size_t len = strlen(string);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen char *to;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen /* All the connections should be identical, so just use the first
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen connected one */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen conn = array_get_modifiable(&db->connections, &count);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (i = 0; i < count; i++) {
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (conn[i].connected)
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (i == count) {
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen /* so, try connecting.. */
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen for (i = 0; i < count; i++) {
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (driver_mysql_connect(&conn[i]))
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen break;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen if (i == count) {
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen /* FIXME: we don't have a valid connection, so fallback
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen to using default escaping. the next query will most
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen likely fail anyway so it shouldn't matter that much
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen what we return here.. Anyway, this API needs
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen changing so that the escaping function could already
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen fail the query reliably. */
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen to = t_buffer_get(len * 2 + 1);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen len = mysql_escape_string(to, string, len);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen t_buffer_alloc(len + 1);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen return to;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen }
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen to = t_buffer_get(len * 2 + 1);
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen len = mysql_real_escape_string(conn[i].mysql, to, string, len);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen t_buffer_alloc(len + 1);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return to;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen}
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_exec(struct sql_db *_db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen (void)driver_mysql_do_query(db, query, &conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void driver_mysql_query(struct sql_db *db, const char *query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback_t *callback, void *context)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct sql_result *result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result = sql_query_s(db, query);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->callback = TRUE;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(result, context);
eeea0a402bcd9533e9e359f2a2518e3216162151Timo Sirainen result->callback = FALSE;
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen sql_result_unref(result);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic struct sql_result *
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_query_s(struct sql_db *_db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_result *result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result = i_new(struct mysql_result, 1);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->api = driver_mysql_result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->api.db = _db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen switch (driver_mysql_do_query(db, query, &conn)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case 0:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* not connected */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->api = sql_not_connected_result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case 1:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* query ok */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->result = mysql_store_result(conn->mysql);
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen if (result->result != NULL || mysql_errno(conn->mysql) == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* fallback */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case -1:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* error */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result->api = driver_mysql_error_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen result->api.refcount = 1;
0546f051db6f510aa84d8c748cb46e584d3fcdfbTimo Sirainen result->conn = conn;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return &result->api;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void driver_mysql_result_free(struct sql_result *_result)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen i_assert(_result != &sql_not_connected_result);
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen if (_result->callback)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (result->result != NULL)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mysql_free_result(result->result);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_next_row(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen if (result->result == NULL) {
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen /* no results */
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen return 0;
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen }
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->row = mysql_fetch_row(result->result);
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen if (result->row != NULL)
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen return 1;
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen return mysql_errno(result->conn->mysql) != 0 ? -1 : 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_result_fetch_fields(struct mysql_result *result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (result->fields != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields_count = mysql_num_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->fields = mysql_fetch_fields(result->result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic unsigned int
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_fields_count(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return result->fields_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_name(struct sql_result *_result, unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(idx < result->fields_count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return result->fields[idx].name;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int driver_mysql_result_find_field(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *field_name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_fetch_fields(result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < result->fields_count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strcmp(result->fields[i].name, field_name) == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return i;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_field_value(struct sql_result *_result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return (const char *)result->row[idx];
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic const unsigned char *
50718cd4318f10c77f82a22477a1625f96928992Timo Sirainendriver_mysql_result_get_field_value_binary(struct sql_result *_result ATTR_UNUSED,
50718cd4318f10c77f82a22477a1625f96928992Timo Sirainen unsigned int idx ATTR_UNUSED,
50718cd4318f10c77f82a22477a1625f96928992Timo Sirainen size_t *size_r ATTR_UNUSED)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen{
50718cd4318f10c77f82a22477a1625f96928992Timo Sirainen /* FIXME */
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return NULL;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_find_field_value(struct sql_result *result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *field_name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen idx = driver_mysql_result_find_field(result, field_name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (idx < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return driver_mysql_result_get_field_value(result, idx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *const *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainendriver_mysql_result_get_values(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return (const char *const *)result->row;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic const char *driver_mysql_result_get_error(struct sql_result *_result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_result *result = (struct mysql_result *)_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return mysql_error(result->conn->mysql);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic struct sql_transaction_context *
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_begin(struct sql_db *db)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx = i_new(struct mysql_transaction_context, 1);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx->ctx.db = db;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->query_pool = pool_alloconly_create("mysql transaction", 1024);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return &ctx->ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_commit(struct sql_transaction_context *ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen sql_commit_callback_t *callback, void *context)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *error;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (sql_transaction_commit_s(&ctx, &error) < 0)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(error, context);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen else
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen callback(NULL, context);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainenstatic int transaction_send_query(struct mysql_transaction_context *ctx,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const char *query)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen{
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen struct sql_result *result;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen my_ulonglong rows;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen int ret = 0;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (ctx->failed)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return -1;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen result = sql_query_s(ctx->ctx.db, query);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (sql_result_next_row(result) < 0) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->error = sql_result_get_error(result);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->failed = TRUE;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = -1;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen } else if (ctx->head != NULL && ctx->head->affected_rows != NULL) {
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen struct mysql_result *my_result = (struct mysql_result *)result;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen rows = mysql_affected_rows(my_result->conn->mysql);
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen i_assert(rows != (my_ulonglong)-1);
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen *ctx->head->affected_rows = rows;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen sql_result_unref(result);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return ret;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen}
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic int
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_commit_s(struct sql_transaction_context *_ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char **error_r)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen int ret = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *error_r = NULL;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (ctx->head != NULL) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen /* try to use a transaction in any case,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen even if it doesn't work. */
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen (void)transaction_send_query(ctx, "BEGIN");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen while (ctx->head != NULL) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (transaction_send_query(ctx, ctx->head->query) < 0)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen break;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->head = ctx->head->next;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ret = transaction_send_query(ctx, "COMMIT");
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen *error_r = ctx->error;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sql_transaction_rollback(&_ctx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_transaction_rollback(struct sql_transaction_context *_ctx)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&ctx->query_pool);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(ctx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainendriver_mysql_update(struct sql_transaction_context *_ctx, const char *query,
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen unsigned int *affected_rows)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen struct mysql_query_list *list;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen list = p_new(ctx->query_pool, struct mysql_query_list, 1);
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen list->query = p_strdup(ctx->query_pool, query);
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen list->affected_rows = affected_rows;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (ctx->head == NULL)
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->head = list;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen else
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->tail->next = list;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen ctx->tail = list;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_db driver_mysql_db = {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "mysql",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen MEMBER(v) {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_init_v,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_deinit_v,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_get_flags,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_connect_all,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_escape_string,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_exec,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_query,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_query_s,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_begin,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_commit,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_commit_s,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_transaction_rollback,
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen driver_mysql_update
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_result driver_mysql_result = {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen MEMBER(v) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_free,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_next_row,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_fields_count,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_name,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_find_field,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_value,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_field_value_binary,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_find_field_value,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_values,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_error
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendriver_mysql_result_error_next_row(struct sql_result *result ATTR_UNUSED)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_result driver_mysql_error_result = {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen MEMBER(v) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_free,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_error_next_row,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen driver_mysql_result_get_error
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_init(void);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_deinit(void);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_init(void)
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen{
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sql_driver_register(&driver_mysql_db);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen}
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid driver_mysql_deinit(void)
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen{
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen sql_driver_unregister(&driver_mysql_db);
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen}
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#endif