driver-mysql.c revision 06b0c3be9905099038964b068216bbed155701de
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen, Alex Howansky */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen#include "buffer.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "sql-api-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#ifdef HAVE_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
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen buffer_t *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
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenextern struct sql_result driver_mysql_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenextern struct sql_result driver_mysql_error_result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic int 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;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen int 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",
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen host, db->dbname, mysql_error(conn->mysql),
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn->connect_delay);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_info("mysql: Connected to %s%s (%s)", host,
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
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstatic void driver_mysql_connect_all(struct mysql_db *db)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t i, size;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size /= sizeof(*conn);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; i++)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen (void)driver_mysql_connect(&conn[i]);
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
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_append_space_unsafe(db->connections, sizeof(*conn));
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
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (db->connections->used == 0)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_fatal("mysql: No hosts given in connect string");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo 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;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen db->connections =
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen buffer_create_dynamic(pool,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen sizeof(struct mysql_connection) * 6);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_parse_connect_string(db, connect_string);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen driver_mysql_connect_all(db);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return &db->api;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo 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;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t i, size;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size /= sizeof(*conn);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; 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;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t size;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen int reset, ret;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen unsigned int i, start;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn = buffer_get_modifyable_data(db->connections, &size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size /= sizeof(*conn);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* go through the connections in round robin. if the connection
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen isn't available, try next one that is. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen start = db->next_query_connection % size;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen db->next_query_connection++;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (reset = 0;; reset++) {
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 */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i = (i + 1) % size;
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. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < size; i++)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen conn[i].connect_delay = CONNECT_RESET_DELAY;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo 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
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void driver_mysql_query(struct sql_db *_db, const char *query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback_t *callback, void *context)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_db *db = (struct mysql_db *)_db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mysql_connection *conn;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mysql_result result;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen switch (driver_mysql_do_query(db, query, &conn)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case 0:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* not connected */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen callback(&sql_not_connected_result, context);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case 1:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* query ok */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memset(&result, 0, sizeof(result));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result.api = driver_mysql_result;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.api.db = _db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.conn = conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.result = mysql_store_result(conn->mysql);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (result.result == NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen callback(&result.api, context);
ef95f34bc41287eb9fd2cea42ddce648d02d5a39Timo Sirainen mysql_free_result(result.result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case -1:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* error */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* error */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen memset(&result, 0, sizeof(result));
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.api = driver_mysql_error_result;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.api.db = _db;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen result.conn = conn;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen callback(&result.api, context);
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
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen result->row = mysql_fetch_row(result->result);
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen if (result->row != NULL)
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen return 1;
a2550844936da8b78d7565b905a4dc5ffb3eef0eTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return mysql_errno(result->conn->mysql) ? -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
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_db driver_mysql_db = {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_init,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_deinit,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen driver_mysql_get_flags,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_exec,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_query
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct sql_result driver_mysql_result = {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
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,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_error
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
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_error_next_row,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL, NULL, NULL, NULL, NULL, NULL,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen driver_mysql_result_get_error
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#endif