view src/lib-sql/sql-api-private.h @ 22656:1789bf2a1e01

director: Make sure HOST-RESET-USERS isn't used with max_moving_users=0 The reset command would just hang in that case. doveadm would never have sent this, so this is just an extra sanity check.
author Timo Sirainen <>
date Sun, 05 Nov 2017 23:51:56 +0200
parents 7d189977dfe3
line wrap: on
line source


#include "sql-api.h"
#include "module-context.h"

enum sql_db_state {
	/* not connected to database */
	/* waiting for connection attempt to succeed or fail */
	/* connected, allowing more queries */
	/* connected, no more queries allowed */

/* Minimum delay between reconnecting to same server */
/* Maximum time to avoiding reconnecting to same server */
#define SQL_CONNECT_MAX_DELAY (60*30)
/* If no servers are connected but a query is requested, try reconnecting to
   next server which has been disconnected longer than this (with a single
   server setup this is really the "max delay" and the SQL_CONNECT_MAX_DELAY
   is never used). */
/* Abort connect() if it can't connect within this time. */
/* Abort queries after this many seconds */
/* Default max. number of connections to create per host */

#define SQL_DB_IS_READY(db) \
	((db)->state == SQL_DB_STATE_IDLE)
#define SQL_ERRSTR_NOT_CONNECTED "Not connected to database"

struct sql_db_module_register {
	unsigned int id;

union sql_db_module_context {
	struct sql_db_module_register *reg;

extern struct sql_db_module_register sql_db_module_register;

struct sql_transaction_query {
	struct sql_transaction_query *next;
	struct sql_transaction_context *trans;

	const char *query;
	unsigned int *affected_rows;

struct sql_db_vfuncs {
	struct sql_db *(*init)(const char *connect_string);
	void (*deinit)(struct sql_db *db);

	int (*connect)(struct sql_db *db);
	void (*disconnect)(struct sql_db *db);
	const char *(*escape_string)(struct sql_db *db, const char *string);

	void (*exec)(struct sql_db *db, const char *query);
	void (*query)(struct sql_db *db, const char *query,
		      sql_query_callback_t *callback, void *context);
	struct sql_result *(*query_s)(struct sql_db *db, const char *query);

	struct sql_transaction_context *(*transaction_begin)(struct sql_db *db);
	void (*transaction_commit)(struct sql_transaction_context *ctx,
				   sql_commit_callback_t *callback,
				   void *context);
	int (*transaction_commit_s)(struct sql_transaction_context *ctx,
				    const char **error_r);
	void (*transaction_rollback)(struct sql_transaction_context *ctx);

	void (*update)(struct sql_transaction_context *ctx, const char *query,
		       unsigned int *affected_rows);
	const char *(*escape_blob)(struct sql_db *db,
				   const unsigned char *data, size_t size);
	void (*transaction_commit2)(struct sql_transaction_context *ctx,
				    sql_commit2_callback_t *callback,
				    void *context);

	struct sql_prepared_statement *
		(*prepared_statement_init)(struct sql_db *db,
					   const char *query_template);
	void (*prepared_statement_deinit)(struct sql_prepared_statement *prep_stmt);

	struct sql_statement *
		(*statement_init)(struct sql_db *db, const char *query_template);
	struct sql_statement *
		(*statement_init_prepared)(struct sql_prepared_statement *prep_stmt);
	void (*statement_abort)(struct sql_statement *stmt);
	void (*statement_set_timestamp)(struct sql_statement *stmt,
					const struct timespec *ts);
	void (*statement_bind_str)(struct sql_statement *stmt,
				   unsigned int column_idx, const char *value);
	void (*statement_bind_binary)(struct sql_statement *stmt,
				      unsigned int column_idx, const void *value,
				      size_t value_size);
	void (*statement_bind_int64)(struct sql_statement *stmt,
				     unsigned int column_idx, int64_t value);
	void (*statement_query)(struct sql_statement *stmt,
				sql_query_callback_t *callback, void *context);
	struct sql_result *(*statement_query_s)(struct sql_statement *stmt);
	void (*update_stmt)(struct sql_transaction_context *ctx,
			    struct sql_statement *stmt,
			    unsigned int *affected_rows);

struct sql_db {
	const char *name;
	enum sql_db_flags flags;

	struct sql_db_vfuncs v;
	ARRAY(union sql_db_module_context *) module_contexts;

	void (*state_change_callback)(struct sql_db *db,
				      enum sql_db_state prev_state,
				      void *context);
	void *state_change_context;

	enum sql_db_state state;
	/* last time we started connecting to this server
	   (which may or may not have succeeded) */
	time_t last_connect_try;
	unsigned int connect_delay;
	unsigned int connect_failure_count;
	struct timeout *to_reconnect;

	unsigned int no_reconnect:1;

struct sql_result_vfuncs {
	void (*free)(struct sql_result *result);
	int (*next_row)(struct sql_result *result);

	unsigned int (*get_fields_count)(struct sql_result *result);
	const char *(*get_field_name)(struct sql_result *result,
				      unsigned int idx);
	int (*find_field)(struct sql_result *result, const char *field_name);

	const char *(*get_field_value)(struct sql_result *result,
				       unsigned int idx);
	const unsigned char *
		(*get_field_value_binary)(struct sql_result *result,
					  unsigned int idx,
					  size_t *size_r);
	const char *(*find_field_value)(struct sql_result *result,
					const char *field_name);
	const char *const *(*get_values)(struct sql_result *result);

	const char *(*get_error)(struct sql_result *result);
	void (*more)(struct sql_result **result, bool async,
		     sql_query_callback_t *callback, void *context);

struct sql_prepared_statement {
	struct sql_db *db;

struct sql_statement {
	struct sql_db *db;

	pool_t pool;
	const char *query_template;
	ARRAY_TYPE(const_string) args;

struct sql_field_map {
	enum sql_field_type type;
	size_t offset;

struct sql_result {
	struct sql_result_vfuncs v;
	int refcount;

	struct sql_db *db;
	const struct sql_field_def *fields;

	unsigned int map_size;
	struct sql_field_map *map;
	void *fetch_dest;
	size_t fetch_dest_size;
	enum sql_result_error_type error_type;

	unsigned int failed:1;
	unsigned int failed_try_retry:1;
	unsigned int callback:1;

struct sql_transaction_context {
	struct sql_db *db;

	/* commit() must use this query list if head is non-NULL. */
	struct sql_transaction_query *head, *tail;

ARRAY_DEFINE_TYPE(sql_drivers, const struct sql_db *);

extern ARRAY_TYPE(sql_drivers) sql_drivers;
extern struct sql_result sql_not_connected_result;

struct sql_db *
driver_sqlpool_init(const char *connect_string, const struct sql_db *driver);

void sql_db_set_state(struct sql_db *db, enum sql_db_state state);

void sql_transaction_add_query(struct sql_transaction_context *ctx, pool_t pool,
			       const char *query, unsigned int *affected_rows);
const char *sql_statement_get_query(struct sql_statement *stmt);