driver-mysql.c revision e180615c1db31c8a6f6a586ae40b1cfc2d6ee725
/* Copyright (c) 2003-2015 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "hex-binary.h"
#include "str.h"
#include "net.h"
#include "sql-api-private.h"
#ifdef BUILD_MYSQL
#include <unistd.h>
#include <time.h>
#ifdef HAVE_ATTR_NULL
/* ugly way to tell clang that mysql.h is a system header and we don't want
to enable nonnull attributes for it by default.. */
#endif
#include <mysql.h>
#ifdef HAVE_ATTR_NULL
# line 20
#endif
#include <errmsg.h>
struct mysql_db {
const char *option_file, *option_group;
unsigned int client_flags;
unsigned int next_query_connection;
unsigned int ssl_set:1;
};
struct mysql_result {
struct sql_result api;
unsigned int fields_count;
};
struct mysql_transaction_context {
struct sql_transaction_context ctx;
const char *error;
unsigned int failed:1;
};
extern const struct sql_db driver_mysql_db;
extern const struct sql_result driver_mysql_result;
extern const struct sql_result driver_mysql_error_result;
{
}
{
const char *unix_socket, *host;
bool failed;
} else {
unix_socket = NULL;
}
db->option_file);
}
#ifdef HAVE_MYSQL_SSL
#ifdef HAVE_MYSQL_SSL_CIPHER
, db->ssl_cipher
#endif
);
(void *)&db->ssl_verify_server_cert);
#endif
#else
i_fatal("mysql: SSL support not compiled in "
"(remove ssl_ca and ssl_ca_path settings)");
#endif
}
#ifdef CLIENT_MULTI_RESULTS
#endif
/* CLIENT_MULTI_RESULTS allows the use of stored procedures */
client_flags) == NULL;
if (failed) {
/* connecting could have taken a while. make sure that any
timeouts that get added soon will get a refreshed
timestamp. */
i_error("%s: Connect failed to database (%s): %s - "
"waiting for %u seconds before retry",
return -1;
} else {
return 1;
}
}
{
}
const char *connect_string)
{
const char **field;
i_fatal("mysql: Missing value in connect string: %s",
*args);
}
value++;
db->ssl_verify_server_cert = 0;
else
else
}
i_fatal("mysql: No hosts given in connect string");
i_fatal("mysql_init() failed");
}
{
T_BEGIN {
} T_END;
}
{
}
{
return 0;
/* failed */
case CR_SERVER_GONE_ERROR:
case CR_SERVER_LOST:
break;
default:
break;
}
return -1;
}
static const char *
{
char *to;
/* try connecting */
}
/* FIXME: we don't have a valid connection, so fallback
to using default escaping. the next query will most
likely fail anyway so it shouldn't matter that much
what we return here.. Anyway, this API needs
changing so that the escaping function could already
fail the query reliably. */
return to;
}
return to;
}
{
i_error("%s: Query '%s' failed: %s",
}
}
{
struct sql_result *result;
}
static struct sql_result *
{
struct mysql_result *result;
int ret;
else {
/* query ok */
#ifdef CLIENT_MULTI_RESULTS
/* Because we've enabled CLIENT_MULTI_RESULTS, we need to read
(ignore) extra results - there should not be any.
ret is: -1 = done, >0 = error, 0 = more results. */
#else
ret = -1;
#endif
if (ret < 0 &&
/* ok */
} else {
/* failed */
}
}
}
{
return;
}
{
int ret;
/* no results */
return 0;
}
ret = 1;
else {
return -1;
ret = 0;
}
return ret;
}
{
return;
}
static unsigned int
{
return result->fields_count;
}
static const char *
{
}
const char *field_name)
{
unsigned int i;
for (i = 0; i < result->fields_count; i++) {
return i;
}
return -1;
}
static const char *
unsigned int idx)
{
}
static const unsigned char *
{
unsigned long *lengths;
}
static const char *
const char *field_name)
{
int idx;
if (idx < 0)
return NULL;
}
static const char *const *
{
}
{
const char *errstr;
unsigned int idle_time;
int err;
db->last_success != 0) {
}
return errstr;
}
static struct sql_transaction_context *
{
struct mysql_transaction_context *ctx;
}
static void
{
const char *error;
else
}
static int ATTR_NULL(3)
unsigned int *affected_rows_r)
{
struct sql_result *_result;
int ret = 0;
return -1;
if (sql_result_next_row(_result) < 0) {
ret = -1;
} else if (affected_rows_r != NULL) {
}
return ret;
}
{
/* try to use a transaction in any case,
even if it's not actually functional. */
return -1;
/* we got disconnected, retry */
return 0;
}
return -1;
}
return -1;
return 1;
}
static int
const char **error_r)
{
struct mysql_transaction_context *ctx =
(struct mysql_transaction_context *)_ctx;
int ret = 1;
if (ret == 0) {
i_info("%s: Disconnected from database, "
}
}
}
return ret <= 0 ? -1 : 0;
}
static void
{
struct mysql_transaction_context *ctx =
(struct mysql_transaction_context *)_ctx;
}
static void
unsigned int *affected_rows)
{
struct mysql_transaction_context *ctx =
(struct mysql_transaction_context *)_ctx;
}
static const char *
{
}
const struct sql_db driver_mysql_db = {
.name = "mysql",
.v = {
}
};
const struct sql_result driver_mysql_result = {
.v = {
}
};
static int
{
return -1;
}
const struct sql_result driver_mysql_error_result = {
.v = {
},
};
const char *driver_mysql_version = DOVECOT_ABI_VERSION;
void driver_mysql_init(void);
void driver_mysql_deinit(void);
void driver_mysql_init(void)
{
}
void driver_mysql_deinit(void)
{
}
#endif