driver-mysql.c revision c95fc202215d2451372599db7092b16459f360a3
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen, Alex Howansky */
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;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int port, client_flags;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen array_t 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
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen string_t *queries;
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
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;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen unsigned int i, count;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen int ret = -1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen conn = array_get_modifyable(&db->connections, &count);
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen for (i = 0; i < count; i++) {
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen if (driver_mysql_connect(&conn[i]))
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 t_push();
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;
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 }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen t_pop();
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen#ifdef CLIENT_MULTI_STATEMENTS
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen /* Updates require this because everything is committed in one large
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen SQL statement. */
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen db->client_flags |= CLIENT_MULTI_STATEMENTS;
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen#endif
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen if (array_count(&db->connections) == 0)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: No hosts given in connect string");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenstatic struct sql_db *_driver_mysql_init(const char *connect_string)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_t pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen pool = pool_alloconly_create("mysql driver", 512);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db = p_new(pool, struct mysql_db, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->pool = pool;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen db->api = driver_mysql_db;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen ARRAY_CREATE(&db->connections, pool, struct mysql_connection, 6);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return &db->api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenstatic void _driver_mysql_deinit(struct sql_db *_db)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen unsigned int i, count;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen conn = array_get_modifyable(&db->connections, &count);
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen for (i = 0; i < count; i++)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen (void)driver_mysql_connection_free(&conn[i]);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_unref(db->pool);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainenstatic enum sql_db_flags
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo 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
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen conn = array_get_modifyable(&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
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainenstatic 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 */
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen conn = array_get_modifyable(&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;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen sql_result_free(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
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
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (_result == &sql_not_connected_result || _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
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;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx->queries = str_new(default_pool, 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
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 struct sql_result *result;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen int ret = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *error_r = NULL;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (str_len(ctx->queries) > 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_append(ctx->queries, "COMMIT;");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen result = sql_query_s(_ctx->db, str_c(ctx->queries));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (sql_result_next_row(result) < 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *error_r = sql_result_get_error(result);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ret = -1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen sql_result_free(result);
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
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen str_free(&ctx->queries);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(ctx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainendriver_mysql_update(struct sql_transaction_context *_ctx, const char *query)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mysql_transaction_context *ctx =
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (struct mysql_transaction_context *)_ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* FIXME: with mysql we're just appending everything into one big
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen string which gets committed in sql_transaction_commit(). we could
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen avoid this if we knew for sure that transactions actually worked,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen but I don't know how to do that.. */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (str_len(ctx->queries) == 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* try to use a transaction in any case,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen even if it doesn't work. */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_append(ctx->queries, "BEGIN;");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_append(ctx->queries, query);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_append_c(ctx->queries, ';');
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_db driver_mysql_db = {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "mysql",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen _driver_mysql_init,
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen _driver_mysql_deinit,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen driver_mysql_get_flags,
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen driver_mysql_connect_all,
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen driver_mysql_escape_string,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_exec,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_query,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_query_s,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_transaction_begin,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_transaction_commit,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_transaction_commit_s,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_transaction_rollback,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_update
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_result driver_mysql_result = {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_result_free,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_next_row,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_fields_count,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_field_name,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_find_field,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_field_value,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_find_field_value,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_values,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_result_get_error,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen FALSE
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo 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 = {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_result_free,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_error_next_row,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL, NULL, NULL, NULL, NULL, NULL,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen driver_mysql_result_get_error,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen FALSE
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