From 36d847a3ee3cf45af9a93d34adbe2a5bcb0fe364 Mon Sep 17 00:00:00 2001 From: Gabor Pali Date: Thu, 7 Sep 2023 15:56:15 +0200 Subject: [PATCH] mango: correct behavior of `fields` on `_explain` The `fields` attribute on `_explain` might have the string value `"all_fields"` when the respective query parameter (`fields`) is not set by the user. This is to express that no projection of fields would happen on the returned documents. The current behavior contradicts with the current contract, because by documentation, `fields` is an array of strings instead to provide information on the projected fields. The discrepancy here makes it hard to formalize this in OpenAPI which leads to problems in the development of SDKs, among others. Change `_explain` to return `[]` for `fields` when it was not set through the query parameters. This is thought to be semantically equivalent to `"all_fields"` therefore this would not cause problems while preserving the promised type. Thanks @ricellis for reporting this problem! --- src/docs/src/api/database/find.rst | 4 +++- src/mango/src/mango_cursor.erl | 16 ++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/docs/src/api/database/find.rst b/src/docs/src/api/database/find.rst index 16a8396403c..62dfb4f80ec 100644 --- a/src/docs/src/api/database/find.rst +++ b/src/docs/src/api/database/find.rst @@ -1401,7 +1401,9 @@ it easier to take advantage of future improvements to query planning :>json object mrargs: Arguments passed to the underlying view. :>json number limit: Limit parameter used. :>json number skip: Skip parameter used. - :>json array fields: Fields to be returned by the query. + :>json array fields: Fields to be returned by the query. The `[]` + value here means all the fields, since there is no projection + happening in that case. :>json boolean partitioned: The database is partitioned or not. :>json array index_candidates: The list of all indexes that were found but not selected for serving the query. See :ref:`the diff --git a/src/mango/src/mango_cursor.erl b/src/mango/src/mango_cursor.erl index c0c8f41dfaa..09d84774e97 100644 --- a/src/mango/src/mango_cursor.erl +++ b/src/mango/src/mango_cursor.erl @@ -294,7 +294,7 @@ extract_selector_hints(Selector) -> | {opts, ejson()} | {limit, integer()} | {skip, integer()} - | {fields, fields()} + | {fields, [field()]} | {index_candidates, [candidate_index()]} | {selector_hints, selector_hints()} | {atom(), any()}. @@ -309,7 +309,7 @@ explain(#cursor{} = Cursor) -> opts = Opts0, limit = Limit, skip = Skip, - fields = Fields + fields = Fields0 } = Cursor, DbName = couch_db:name(Db), Partitioned = fabric_util:is_partitioned(Db), @@ -332,6 +332,11 @@ explain(#cursor{} = Cursor) -> false -> Opts1 end, + Fields = + case Fields0 of + all_fields -> []; + Value -> Value + end, CandidateIndexes = extract_candidate_indexes(Cursor), SelectorHints = extract_selector_hints(Selector), { @@ -1091,7 +1096,6 @@ explain_test_() -> t_explain_empty(_) -> Selector = {[]}, Indexes = sets:new(), - Fields = all_fields, Trace = #{ all_indexes => Indexes, @@ -1110,7 +1114,7 @@ t_explain_empty(_) -> opts = [{user_ctx, user_ctx}], limit = limit, skip = skip, - fields = Fields, + fields = all_fields, trace = Trace }, Hints = [{[{type, json}, {indexable_fields, []}, {unindexable_fields, []}]}], @@ -1123,7 +1127,7 @@ t_explain_empty(_) -> {opts, {[]}}, {limit, limit}, {skip, skip}, - {fields, Fields}, + {fields, []}, {index_candidates, []}, {selector_hints, Hints} ]}, @@ -1140,7 +1144,7 @@ t_explain_regular(_) -> }, Selector = {[]}, Indexes = sets:from_list([Index]), - Fields = all_fields, + Fields = some_fields, Trace = #{ all_indexes => Indexes,