bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
f69bd378b6454dc6498f7d35356ec651123e96a6Timo Sirainenstruct sql_db_module_register sql_db_module_register = { 0 };
903507ced4fed650d36782a897e5a56a1978367aTimo Sirainenstatic const struct sql_db *sql_driver_lookup(const char *name)
903507ced4fed650d36782a897e5a56a1978367aTimo Sirainen for (i = 0; i < count; i++) {
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid sql_driver_register(const struct sql_db *driver)
903507ced4fed650d36782a897e5a56a1978367aTimo Sirainen if (sql_driver_lookup(driver->name) != NULL) {
903507ced4fed650d36782a897e5a56a1978367aTimo Sirainen i_fatal("sql_driver_register(%s): Already registered",
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainenvoid sql_driver_unregister(const struct sql_db *driver)
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen for (i = 0; i < count; i++) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstruct sql_db *sql_init(const char *db_driver, const char *connect_string)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_fatal("Unknown database driver '%s'", db_driver);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((driver->flags & SQL_DB_FLAG_POOLED) == 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen db = driver_sqlpool_init(connect_string, driver);
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainenenum sql_db_flags sql_get_flags(struct sql_db *db)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* don't try reconnecting more than once a second */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (db->last_connect_try + (time_t)db->connect_delay > now)
13a8c553f293349248b161ff851743498916e26eTimo Sirainenconst char *sql_escape_string(struct sql_db *db, const char *string)
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainenvoid sql_exec(struct sql_db *db, const char *query)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid sql_query(struct sql_db *db, const char *query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback_t *callback, void *context)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstruct sql_result *sql_query_s(struct sql_db *db, const char *query)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainendefault_sql_prepared_statement_init(struct sql_db *db,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen struct default_sql_prepared_statement *prep_stmt;
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen prep_stmt = i_new(struct default_sql_prepared_statement, 1);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen prep_stmt->query_template = i_strdup(query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainendefault_sql_prepared_statement_deinit(struct sql_prepared_statement *_prep_stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen struct default_sql_prepared_statement *prep_stmt =
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen (struct default_sql_prepared_statement *)_prep_stmt;
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainendefault_sql_statement_init_prepared(struct sql_prepared_statement *_stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen (struct default_sql_prepared_statement *)_stmt;
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen return sql_statement_init(_stmt->db, stmt->query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenconst char *sql_statement_get_query(struct sql_statement *stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen for (i = 0; stmt->query_template[i] != '\0'; i++) {
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen i_panic("lib-sql: Missing bind for arg #%u in statement: %s",
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen i_panic("lib-sql: Too many bind args (%u) for statement: %s",
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainendefault_sql_statement_query(struct sql_statement *stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_query_callback_t *callback, void *context)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_query(stmt->db, sql_statement_get_query(stmt),
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenstatic struct sql_result *
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainendefault_sql_statement_query_s(struct sql_statement *stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_query_s(stmt->db, sql_statement_get_query(stmt));
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenstatic void default_sql_update_stmt(struct sql_transaction_context *ctx,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen ctx->db->v.update(ctx, sql_statement_get_query(stmt),
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainensql_prepared_statement_init(struct sql_db *db, const char *query_template)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen return db->v.prepared_statement_init(db, query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen return default_sql_prepared_statement_init(db, query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_prepared_statement_deinit(struct sql_prepared_statement **_prep_stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen struct sql_prepared_statement *prep_stmt = *_prep_stmt;
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen if (prep_stmt->db->v.prepared_statement_deinit != NULL)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen prep_stmt->db->v.prepared_statement_deinit(prep_stmt);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen default_sql_prepared_statement_deinit(prep_stmt);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainensql_statement_init_fields(struct sql_statement *stmt, struct sql_db *db)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainensql_statement_init(struct sql_db *db, const char *query_template)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt = db->v.statement_init(db, query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen pool_t pool = pool_alloconly_create("sql statement", 1024);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->query_template = p_strdup(stmt->pool, query_template);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainensql_statement_init_prepared(struct sql_prepared_statement *prep_stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen if (prep_stmt->db->v.statement_init_prepared == NULL)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen return default_sql_statement_init_prepared(prep_stmt);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt = prep_stmt->db->v.statement_init_prepared(prep_stmt);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_statement_init_fields(stmt, prep_stmt->db);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_abort(struct sql_statement **_stmt)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_set_timestamp(struct sql_statement *stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen if (stmt->db->v.statement_set_timestamp != NULL)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->db->v.statement_set_timestamp(stmt, ts);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_bind_str(struct sql_statement *stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen array_idx_set(&stmt->args, column_idx, &escaped_value);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->db->v.statement_bind_str(stmt, column_idx, value);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_bind_binary(struct sql_statement *stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_escape_blob(stmt->db, value, value_size));
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen array_idx_set(&stmt->args, column_idx, &value_str);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen if (stmt->db->v.statement_bind_binary != NULL) {
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->db->v.statement_bind_binary(stmt, column_idx,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_bind_int64(struct sql_statement *stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen const char *value_str = p_strdup_printf(stmt->pool, "%"PRId64, value);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen array_idx_set(&stmt->args, column_idx, &value_str);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->db->v.statement_bind_int64(stmt, column_idx, value);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_statement_query(struct sql_statement **_stmt,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen sql_query_callback_t *callback, void *context)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen stmt->db->v.statement_query(stmt, callback, context);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen default_sql_statement_query(stmt, callback, context);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenstruct sql_result *sql_statement_query_s(struct sql_statement **_stmt)
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainenvoid sql_result_unref(struct sql_result *result)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic const struct sql_field_def *
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainensql_field_def_find(const struct sql_field_def *fields, const char *name)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen unsigned int i;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainensql_result_build_map(struct sql_result *result,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen const struct sql_field_def *fields, size_t dest_size)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen result->map = i_new(struct sql_field_map, result->map_size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen for (i = 0; i < count; i++) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen field_size = sizeof(const char *);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen field_size = sizeof(unsigned int);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen field_size = sizeof(unsigned long long);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen field_size = sizeof(bool);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen i_assert(def->offset + field_size <= dest_size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenvoid sql_result_setup_fetch(struct sql_result *result,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen sql_result_build_map(result, fields, dest_size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstatic void sql_result_fetch(struct sql_result *result)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen memset(result->fetch_dest, 0, result->fetch_dest_size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen for (i = 0; i < count; i++) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen value = sql_result_get_field_value(result, i);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen str_to_ullong(value, (unsigned long long *)ptr) < 0)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (value != NULL && (*value == 't' || *value == '1'))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint sql_result_next_row(struct sql_result *result)
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainenvoid sql_result_more(struct sql_result **result,
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainen sql_query_callback_t *callback, void *context)
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainen (*result)->v.more(result, TRUE, callback, context);
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainensql_result_more_sync_callback(struct sql_result *result, void *context)
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainenvoid sql_result_more_s(struct sql_result **result)
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainen (*result)->v.more(result, FALSE, sql_result_more_sync_callback, result);
065189672f2e741255ac22b158a23207b0ab05a3Timo Sirainen /* the callback must have been called */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenunsigned int sql_result_get_fields_count(struct sql_result *result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenconst char *sql_result_get_field_name(struct sql_result *result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint sql_result_find_field(struct sql_result *result, const char *field_name)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return result->v.find_field(result, field_name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenconst char *sql_result_get_field_value(struct sql_result *result,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return result->v.get_field_value(result, idx);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenconst unsigned char *
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainensql_result_get_field_value_binary(struct sql_result *result,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return result->v.get_field_value_binary(result, idx, size_r);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenconst char *sql_result_find_field_value(struct sql_result *result,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return result->v.find_field_value(result, field_name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenconst char *const *sql_result_get_values(struct sql_result *result)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenconst char *sql_result_get_error(struct sql_result *result)
1601169d6f6004e0656238ed7691c16f3aab61aaTimo Sirainenenum sql_result_error_type sql_result_get_error_type(struct sql_result *result)
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainensql_result_not_connected_free(struct sql_result *result ATTR_UNUSED)
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainensql_result_not_connected_next_row(struct sql_result *result ATTR_UNUSED)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainensql_result_not_connected_get_error(struct sql_result *result ATTR_UNUSED)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstruct sql_transaction_context *sql_transaction_begin(struct sql_db *db)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid sql_transaction_commit(struct sql_transaction_context **_ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen sql_commit_callback_t *callback, void *context)
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen ctx->db->v.transaction_commit(ctx, callback, context);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenint sql_transaction_commit_s(struct sql_transaction_context **_ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char **error_r)
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen return ctx->db->v.transaction_commit_s(ctx, error_r);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid sql_transaction_rollback(struct sql_transaction_context **_ctx)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenvoid sql_update(struct sql_transaction_context *ctx, const char *query)
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_update_stmt(struct sql_transaction_context *ctx,
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainenvoid sql_update_get_rows(struct sql_transaction_context *ctx, const char *query,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainenvoid sql_update_stmt_get_rows(struct sql_transaction_context *ctx,
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen ctx->db->v.update_stmt(ctx, stmt, affected_rows);
9f0fc74e3387d3e496fb0c8f77633e27e48cc1ffTimo Sirainen default_sql_update_stmt(ctx, stmt, affected_rows);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid sql_db_set_state(struct sql_db *db, enum sql_db_state state)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid sql_transaction_add_query(struct sql_transaction_context *ctx, pool_t pool,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const char *query, unsigned int *affected_rows)