c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo SirainenARRAY_DEFINE_TYPE(sql_dict_param, struct sql_dict_param);
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen unsigned int path_idx, sql_fields_start_idx, next_map_idx;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen bool allow_null_map; /* allow next map to be NULL */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen dict_transaction_commit_callback_t *async_callback;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void sql_dict_prev_inc_flush(struct sql_dict_transaction_context *ctx);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstatic void sql_dict_prev_set_flush(struct sql_dict_transaction_context *ctx);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainensql_dict_init(struct dict *driver, const char *uri,
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen pool = pool_alloconly_create("sql dict", 2048);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen dict->username = p_strdup(pool, set->username);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen dict->set = dict_sql_settings_read(uri, error_r);
5ec4fc44e8d4e2160f07b1a7f4fce1ccfec3f6c1Timo Sirainen /* currently pgsql and sqlite don't support "ON DUPLICATE KEY" */
5ec4fc44e8d4e2160f07b1a7f4fce1ccfec3f6c1Timo Sirainen dict->has_on_duplicate_key = strcmp(driver->name, "mysql") == 0;
5ec4fc44e8d4e2160f07b1a7f4fce1ccfec3f6c1Timo Sirainen dict->db = sql_db_cache_new(dict_sql_db_cache, driver->name,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if ((sql_get_flags(dict->db) & SQL_DB_FLAG_PREP_STATEMENTS) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hash_table_create(&dict->prep_stmt_hash, dict->pool,
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainenstatic void sql_dict_prep_stmt_hash_free(struct sql_dict *dict)
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen if (!hash_table_is_created(dict->prep_stmt_hash))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen iter = hash_table_iterate_init(dict->prep_stmt_hash);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen while (hash_table_iterate(iter, dict->prep_stmt_hash, &query, &prep_stmt))
34d5077c37dc6224a2d430a72ae51a3f38e9e4f6Timo Sirainenstatic void sql_dict_deinit(struct dict *_dict)
34d5077c37dc6224a2d430a72ae51a3f38e9e4f6Timo Sirainen struct sql_dict *dict = (struct sql_dict *)_dict;
b56679429b82dfea1ceecc40efea50dd8e4e0ac5Timo Sirainenstatic void sql_dict_wait(struct dict *dict ATTR_UNUSED)
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen /* FIXME: lib-sql doesn't support this yet */
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainendict_sql_map_match(const struct dict_sql_map *map, const char *path,
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen ARRAY_TYPE(const_string) *values, size_t *pat_len_r,
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen size_t *path_len_r, bool partial_ok, bool recurse)
34d5077c37dc6224a2d430a72ae51a3f38e9e4f6Timo Sirainen /* variable */
34d5077c37dc6224a2d430a72ae51a3f38e9e4f6Timo Sirainen /* pattern ended with this variable,
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen it'll match the rest of the path */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* iterating - the last field never
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen matches fully. if there's a trailing
84717f00ddbf5cd0ebe3f285090d5e97e458e19cTimo Sirainen '/', drop it. */
7660a5183e89459d255dc5873894ff08806711d5Timo Sirainen /* pattern matches until the next '/' in path */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* no '/' anymore, but it'll still match a
f8b6c3d6bc9d63665af5e0a3c8b604438e4c3a4eTimo Sirainen /* partial matches must end with '/'. */
71da447014454c84828d9dface77219875554d7dTimo Sirainen /* if we're not recursing, there should be only one $variable
71da447014454c84828d9dface77219875554d7dTimo Sirainen return pat[0] == '$' && strchr(pat, '/') == NULL;
static const struct dict_sql_map *
for (i = 0; i < count; i++) {
return &maps[i];
return NULL;
case DICT_SQL_TYPE_STRING:
case DICT_SQL_TYPE_INT:
case DICT_SQL_TYPE_UINT:
case DICT_SQL_TYPE_HEXBLOB:
static struct sql_statement *
param);
return stmt;
switch (value_type) {
case DICT_SQL_TYPE_STRING:
case DICT_SQL_TYPE_INT:
case DICT_SQL_TYPE_UINT:
case DICT_SQL_TYPE_HEXBLOB:
const char **error_r)
const char **error_r)
for (i = 0; i < exact_count; i++) {
switch (recurse_type) {
case SQL_DICT_RECURSE_NONE:
case SQL_DICT_RECURSE_ONE:
if (i < count2) {
case SQL_DICT_RECURSE_FULL:
if (i < count2) {
if (priv) {
if (count2 > 0)
const char **error_r)
switch (type) {
case DICT_SQL_TYPE_STRING:
case DICT_SQL_TYPE_INT:
case DICT_SQL_TYPE_UINT:
case DICT_SQL_TYPE_HEXBLOB:
return values;
unsigned int sql_field_idx)
if (ret < 0) {
} else if (ret > 0) {
return ret;
static const struct dict_sql_map *
(recurse ||
return &maps[i];
return NULL;
const char **error_r)
if (i == count) {
i_assert(i > 0);
for (; i < count; i++)
for (i = 0; i < count; i++) {
if (ret <= 0) {
if (ret == 0)
return ret;
return ret;
static struct dict_iterate_context *
for (i = 0; i < path_count; i++)
return FALSE;
return FALSE;
return FALSE;
return FALSE;
if (ret == 0) {
return FALSE;
if (ret < 0) {
return FALSE;
i++; sql_field_i++;
return TRUE;
const char **error_r)
return ret;
static struct dict_transaction_context *
return TRUE;
return FALSE;
void *context)
} else if (async) {
static struct sql_statement *
const char *query,
return stmt;
const char **error_r)
for (i = 0; i < field_count; i++) {
for (i = 0; i < count; i++) {
for (i = 0; i < field_count; i++) {
const char **error_r)
for (i = 0; i < field_count; i++) {
const char *key)
return FALSE;
return FALSE;
return FALSE;
return FALSE;
for (i = 0; i < count1; i++) {
return FALSE;
return TRUE;
for (i = 0; i < count; i++) {