/* Copyright (c) 2003-2018 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 {
unsigned int client_flags;
unsigned int next_query_connection;
};
struct mysql_result {
unsigned int fields_count;
};
struct mysql_transaction_context {
const char *error;
};
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;
{
}
{
unsigned int secs_used;
bool failed;
/* assume option_file overrides the host, or if not we'll just
connect to localhost */
unix_socket = NULL;
} 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",
}
}
{
}
static struct sql_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 *
{
}
static void
{
const char *error;
}
static int ATTR_NULL(3)
unsigned int *affected_rows_r)
{
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;
if (ret == 0) {
i_info("%s: Disconnected from database, "
}
}
}
return ret <= 0 ? -1 : 0;
}
static void
{
(struct mysql_transaction_context *)_ctx;
}
static void
unsigned int *affected_rows)
{
(struct mysql_transaction_context *)_ctx;
}
static const char *
{
}
.name = "mysql",
.v = {
}
};
.v = {
}
};
static int
{
return -1;
}
.v = {
},
};
void driver_mysql_init(void);
void driver_mysql_deinit(void);
void driver_mysql_init(void)
{
}
void driver_mysql_deinit(void)
{
}
#endif