]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict: Change dict.iterate() API to support returning multiple values
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 17 Nov 2020 12:09:30 +0000 (14:09 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Mon, 23 Nov 2020 12:04:46 +0000 (12:04 +0000)
This requires changes to all dict drivers.

src/lib-dict-backend/dict-sql.c
src/lib-dict-extra/dict-fs.c
src/lib-dict/dict-client.c
src/lib-dict/dict-fail.c
src/lib-dict/dict-file.c
src/lib-dict/dict-private.h
src/lib-dict/dict.c

index 97a70a9b0375ea2e006adad488aa2a4660ed7d65..f2027b992625d8d2871371a9d890f1de29f33421 100644 (file)
@@ -50,6 +50,7 @@ struct sql_dict_iterate_context {
        bool synchronous_result;
        bool iter_query_sent;
        bool allow_null_map; /* allow next map to be NULL */
+       const char *values[2];
        const char *error;
 };
 
@@ -781,7 +782,7 @@ sql_dict_iterate_init(struct dict *_dict, const char *const *paths,
 }
 
 static bool sql_dict_iterate(struct dict_iterate_context *_ctx,
-                            const char **key_r, const char **value_r)
+                            const char **key_r, const char *const **values_r)
 {
        struct sql_dict_iterate_context *ctx =
                (struct sql_dict_iterate_context *)_ctx;
@@ -832,7 +833,7 @@ static bool sql_dict_iterate(struct dict_iterate_context *_ctx,
                /* we have gotten *SOME* results, so can allow
                   unmapped next key now. */
                ctx->allow_null_map = TRUE;
-               return sql_dict_iterate(_ctx, key_r, value_r);
+               return sql_dict_iterate(_ctx, key_r, values_r);
        }
        if (ret < 0) {
                ctx->error = p_strdup_printf(ctx->pool,
@@ -866,8 +867,9 @@ static bool sql_dict_iterate(struct dict_iterate_context *_ctx,
 
        *key_r = str_c(ctx->key);
        if ((ctx->flags & DICT_ITERATE_FLAG_NO_VALUE) == 0) {
-               *value_r = sql_dict_result_unescape_value(ctx->map,
+               ctx->values[0] = sql_dict_result_unescape_value(ctx->map,
                                        pool_datastack_create(), ctx->result);
+               *values_r = ctx->values;
        }
        return TRUE;
 }
index 446a902522f7b545d5fd3dff03aa112d6e43de6d..31af57867e8bd3d493bbf7027f9c733d84170a06 100644 (file)
@@ -21,6 +21,7 @@ struct fs_dict_iterate_context {
        enum dict_iterate_flags flags;
        pool_t value_pool;
        struct fs_iter *fs_iter;
+       const char *values[2];
        char *error;
 };
 
@@ -145,7 +146,7 @@ fs_dict_iterate_init(struct dict *_dict, const char *const *paths,
 }
 
 static bool fs_dict_iterate(struct dict_iterate_context *ctx,
-                           const char **key_r, const char **value_r)
+                           const char **key_r, const char *const **values_r)
 {
        struct fs_dict_iterate_context *iter =
                (struct fs_dict_iterate_context *)ctx;
@@ -166,23 +167,27 @@ static bool fs_dict_iterate(struct dict_iterate_context *ctx,
                        return FALSE;
                path = fs_dict_get_full_key(dict, iter->paths[iter->path_idx]);
                iter->fs_iter = fs_iter_init(dict->fs, path, 0);
-               return fs_dict_iterate(ctx, key_r, value_r);
+               return fs_dict_iterate(ctx, key_r, values_r);
        }
        path = t_strconcat(iter->paths[iter->path_idx], *key_r, NULL);
        if ((iter->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) {
+               iter->values[0] = NULL;
                *key_r = path;
                return TRUE;
        }
        p_clear(iter->value_pool);
-       if ((ret = fs_dict_lookup(ctx->dict, iter->value_pool, path, value_r, &error)) < 0) {
+       ret = fs_dict_lookup(ctx->dict, iter->value_pool, path,
+                            &iter->values[0], &error);
+       if (ret < 0) {
                /* I/O error */
                iter->error = i_strdup(error);
                return FALSE;
        } else if (ret == 0) {
                /* file was just deleted, just skip to next one */
-               return fs_dict_iterate(ctx, key_r, value_r);
+               return fs_dict_iterate(ctx, key_r, values_r);
        }
        *key_r = path;
+       *values_r = iter->values;
        return TRUE;
 }
 
index f432b6c5dabd21b080ae9956a9c68d797f832f32..f247921e4784680ad2a12170670d63e94a25be7b 100644 (file)
@@ -105,6 +105,7 @@ struct client_dict_iterate_context {
        pool_t results_pool;
        ARRAY(struct client_dict_iter_result) results;
        unsigned int result_idx;
+       const char *values[2];
 
        bool cmd_sent;
        bool seen_results;
@@ -1184,7 +1185,7 @@ client_dict_iterate_cmd_send(struct client_dict_iterate_context *ctx)
 }
 
 static bool client_dict_iterate(struct dict_iterate_context *_ctx,
-                               const char **key_r, const char **value_r)
+                               const char **key_r, const char *const **values_r)
 {
        struct client_dict_iterate_context *ctx =
                (struct client_dict_iterate_context *)_ctx;
@@ -1199,7 +1200,8 @@ static bool client_dict_iterate(struct dict_iterate_context *_ctx,
        results = array_get(&ctx->results, &count);
        if (ctx->result_idx < count) {
                *key_r = results[ctx->result_idx].key;
-               *value_r = results[ctx->result_idx].value;
+               ctx->values[0] = results[ctx->result_idx].value;
+               *values_r = ctx->values;
                ctx->ctx.has_more = TRUE;
                ctx->result_idx++;
                ctx->seen_results = TRUE;
@@ -1208,7 +1210,7 @@ static bool client_dict_iterate(struct dict_iterate_context *_ctx,
        if (!ctx->cmd_sent) {
                ctx->cmd_sent = TRUE;
                client_dict_iterate_cmd_send(ctx);
-               return client_dict_iterate(_ctx, key_r, value_r);
+               return client_dict_iterate(_ctx, key_r, values_r);
        }
        ctx->ctx.has_more = !ctx->finished;
        ctx->result_idx = 0;
@@ -1217,7 +1219,7 @@ static bool client_dict_iterate(struct dict_iterate_context *_ctx,
 
        if ((ctx->flags & DICT_ITERATE_FLAG_ASYNC) == 0 && ctx->ctx.has_more) {
                client_dict_wait(_ctx->dict);
-               return client_dict_iterate(_ctx, key_r, value_r);
+               return client_dict_iterate(_ctx, key_r, values_r);
        }
        return FALSE;
 }
index ebd32eb65d3c2381cf7106efcf3eb18f73d79ae7..ad35d063575ce46f41fe294f2ce9342643e84058 100644 (file)
@@ -47,7 +47,8 @@ dict_fail_iterate_init(struct dict *dict ATTR_UNUSED, const char *const *paths A
 }
 
 static bool dict_fail_iterate(struct dict_iterate_context *ctx ATTR_UNUSED,
-                             const char **key_r ATTR_UNUSED, const char **value_r ATTR_UNUSED)
+                             const char **key_r ATTR_UNUSED,
+                             const char *const **values_r ATTR_UNUSED)
 {
        return FALSE;
 }
index 70db4fbf7d59a303c329849da68dc98033817096..8ffeb236a09579a8aeeaae99d654343ebef85539 100644 (file)
@@ -46,6 +46,7 @@ struct file_dict_iterate_context {
        struct file_dict_iterate_path *paths;
 
        enum dict_iterate_flags flags;
+       const char *values[2];
        const char *error;
 };
 
@@ -252,7 +253,7 @@ file_dict_iterate_find_path(struct file_dict_iterate_context *ctx,
 }
 
 static bool file_dict_iterate(struct dict_iterate_context *_ctx,
-                             const char **key_r, const char **value_r)
+                             const char **key_r, const char *const **values_r)
 {
        struct file_dict_iterate_context *ctx =
                (struct file_dict_iterate_context *)_ctx;
@@ -277,7 +278,8 @@ static bool file_dict_iterate(struct dict_iterate_context *_ctx,
                }
 
                *key_r = key;
-               *value_r = value;
+               ctx->values[0] = value;
+               *values_r = ctx->values;
                return TRUE;
        }
        return FALSE;
index fc832ecef5648063156182cba9bf6e834aca9272..5ff7c56ba7572336233b8b1cf4a7fa83d04a1768 100644 (file)
@@ -21,7 +21,7 @@ struct dict_vfuncs {
                (*iterate_init)(struct dict *dict, const char *const *paths,
                                enum dict_iterate_flags flags);
        bool (*iterate)(struct dict_iterate_context *ctx,
-                       const char **key_r, const char **value_r);
+                       const char **key_r, const char *const **values_r);
        int (*iterate_deinit)(struct dict_iterate_context *ctx,
                              const char **error_r);
 
index 997fe030b191676eea28db635af8669bbe8ecceb..936c747c4fbf1d5eaecd98cb515962cb79aad9c9 100644 (file)
@@ -382,6 +382,8 @@ dict_iterate_init_multiple(struct dict *dict, const char *const *paths,
 bool dict_iterate(struct dict_iterate_context *ctx,
                  const char **key_r, const char **value_r)
 {
+       const char *const *values;
+
        if (ctx->max_rows > 0 && ctx->row_count >= ctx->max_rows) {
                e_debug(ctx->event, "Maximum row count (%"PRIu64") reached",
                        ctx->max_rows);
@@ -389,12 +391,15 @@ bool dict_iterate(struct dict_iterate_context *ctx,
                ctx->has_more = FALSE;
                return FALSE;
        }
-       if (!ctx->dict->v.iterate(ctx, key_r, value_r))
+       if (!ctx->dict->v.iterate(ctx, key_r, &values))
                return FALSE;
        if ((ctx->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) {
                /* always return value as NULL to be consistent across
                   drivers */
                *value_r = NULL;
+       } else {
+               i_assert(values[0] != NULL);
+               *value_r = values[0];
        }
        ctx->row_count++;
        return TRUE;