summaryrefslogtreecommitdiffstats
path: root/src/lib-sql/sql-api-private.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-sql/sql-api-private.h')
-rw-r--r--src/lib-sql/sql-api-private.h251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/lib-sql/sql-api-private.h b/src/lib-sql/sql-api-private.h
new file mode 100644
index 0000000..192afb6
--- /dev/null
+++ b/src/lib-sql/sql-api-private.h
@@ -0,0 +1,251 @@
+#ifndef SQL_API_PRIVATE_H
+#define SQL_API_PRIVATE_H
+
+#include "sql-api.h"
+#include "module-context.h"
+
+enum sql_db_state {
+ /* not connected to database */
+ SQL_DB_STATE_DISCONNECTED,
+ /* waiting for connection attempt to succeed or fail */
+ SQL_DB_STATE_CONNECTING,
+ /* connected, allowing more queries */
+ SQL_DB_STATE_IDLE,
+ /* connected, no more queries allowed */
+ SQL_DB_STATE_BUSY
+};
+
+/* Minimum delay between reconnecting to same server */
+#define SQL_CONNECT_MIN_DELAY 1
+/* 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). */
+#define SQL_CONNECT_RESET_DELAY 15
+/* Abort connect() if it can't connect within this time. */
+#define SQL_CONNECT_TIMEOUT_SECS 5
+/* Abort queries after this many seconds */
+#define SQL_QUERY_TIMEOUT_SECS 60
+/* Default max. number of connections to create per host */
+#define SQL_DEFAULT_CONNECTION_LIMIT 5
+
+#define SQL_DB_IS_READY(db) \
+ ((db)->state == SQL_DB_STATE_IDLE)
+#define SQL_ERRSTR_NOT_CONNECTED "Not connected to database"
+
+/* What is considered slow query */
+#define SQL_SLOW_QUERY_MSEC 1000
+
+#define SQL_QUERY_FINISHED "sql_query_finished"
+#define SQL_CONNECTION_FINISHED "sql_connection_finished"
+#define SQL_TRANSACTION_FINISHED "sql_transaction_finished"
+
+#define SQL_QUERY_FINISHED_FMT "Finished query '%s' in %u msecs"
+
+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;
+
+extern struct event_category event_category_sql;
+
+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);
+ int (*init_full)(const struct sql_settings *set, struct sql_db **db_r,
+ const char **error);
+ void (*deinit)(struct sql_db *db);
+ void (*unref)(struct sql_db *db);
+ void (*wait) (struct sql_db *db);
+
+ enum sql_db_flags (*get_flags)(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);
+
+ 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;
+ int refcount;
+
+ 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;
+
+ struct event *event;
+ HASH_TABLE(char *, struct sql_prepared_statement *) prepared_stmt_hash;
+
+ 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;
+
+ uint64_t succeeded_queries;
+ uint64_t failed_queries;
+ /* includes both succeeded and failed */
+ uint64_t slow_queries;
+
+ bool 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;
+ int refcount;
+ char *query_template;
+};
+
+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;
+ struct event *event;
+ size_t fetch_dest_size;
+ enum sql_result_error_type error_type;
+
+ bool failed:1;
+ bool failed_try_retry:1;
+ bool callback:1;
+};
+
+struct sql_transaction_context {
+ struct sql_db *db;
+ struct event *event;
+
+ /* 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;
+
+void sql_init_common(struct sql_db *db);
+struct sql_db *
+driver_sqlpool_init(const char *connect_string, const struct sql_db *driver);
+int driver_sqlpool_init_full(const struct sql_settings *set, const struct sql_db *driver,
+ struct sql_db **db_r, const char **error_r);
+
+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);
+
+void sql_connection_log_finished(struct sql_db *db);
+struct event_passthrough *
+sql_query_finished_event(struct sql_db *db, struct event *event, const char *query,
+ bool success, int *duration_r);
+struct event_passthrough *sql_transaction_finished_event(struct sql_transaction_context *ctx);
+#endif