From: Timo Sirainen Date: Tue, 17 Nov 2020 12:09:30 +0000 (+0200) Subject: lib-dict: Change dict.iterate() API to support returning multiple values X-Git-Tag: 2.3.14.rc1~330 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65b7f04f945781cd042f5ad2f6f104f532143ee7;p=thirdparty%2Fdovecot%2Fcore.git lib-dict: Change dict.iterate() API to support returning multiple values This requires changes to all dict drivers. --- diff --git a/src/lib-dict-backend/dict-sql.c b/src/lib-dict-backend/dict-sql.c index 97a70a9b03..f2027b9926 100644 --- a/src/lib-dict-backend/dict-sql.c +++ b/src/lib-dict-backend/dict-sql.c @@ -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; } diff --git a/src/lib-dict-extra/dict-fs.c b/src/lib-dict-extra/dict-fs.c index 446a902522..31af57867e 100644 --- a/src/lib-dict-extra/dict-fs.c +++ b/src/lib-dict-extra/dict-fs.c @@ -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; } diff --git a/src/lib-dict/dict-client.c b/src/lib-dict/dict-client.c index f432b6c5da..f247921e47 100644 --- a/src/lib-dict/dict-client.c +++ b/src/lib-dict/dict-client.c @@ -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; } diff --git a/src/lib-dict/dict-fail.c b/src/lib-dict/dict-fail.c index ebd32eb65d..ad35d06357 100644 --- a/src/lib-dict/dict-fail.c +++ b/src/lib-dict/dict-fail.c @@ -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; } diff --git a/src/lib-dict/dict-file.c b/src/lib-dict/dict-file.c index 70db4fbf7d..8ffeb236a0 100644 --- a/src/lib-dict/dict-file.c +++ b/src/lib-dict/dict-file.c @@ -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; diff --git a/src/lib-dict/dict-private.h b/src/lib-dict/dict-private.h index fc832ecef5..5ff7c56ba7 100644 --- a/src/lib-dict/dict-private.h +++ b/src/lib-dict/dict-private.h @@ -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); diff --git a/src/lib-dict/dict.c b/src/lib-dict/dict.c index 997fe030b1..936c747c4f 100644 --- a/src/lib-dict/dict.c +++ b/src/lib-dict/dict.c @@ -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;