You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ii...@apache.org on 2025/06/25 19:10:15 UTC
(couchdb) 07/10: Implement csrt:query/2 and csrt:query/4
This is an automated email from the ASF dual-hosted git repository.
iilyak pushed a commit to branch couch-stats-resource-tracker-v3-rebase-http-2
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit b0bad086fbb0d952892d1605ee3c102c73b5bef3
Author: ILYA Khlopotov <ii...@apache.org>
AuthorDate: Wed Jun 25 11:03:56 2025 -0700
Implement csrt:query/2 and csrt:query/4
---
src/couch_stats/src/csrt.erl | 23 +++++---
src/couch_stats/src/csrt_query.erl | 105 +++++++++++++++++++++++++++++++------
2 files changed, 105 insertions(+), 23 deletions(-)
diff --git a/src/couch_stats/src/csrt.erl b/src/couch_stats/src/csrt.erl
index 08678d248..1864f9f44 100644
--- a/src/couch_stats/src/csrt.erl
+++ b/src/couch_stats/src/csrt.erl
@@ -92,8 +92,8 @@
find_workers_by_pidref/1,
group_by/2,
group_by/3,
- query/1,
query/2,
+ query/4,
query_matcher/1,
query_matcher/2,
sorted/1,
@@ -495,14 +495,21 @@ query_matcher(MatcherName) ->
query_matcher(MatcherName, Limit) ->
csrt_query:query_matcher(MatcherName, Limit).
--spec query(Keys :: string() | [string()], Options :: query_options()) -> {ok, query_result()}
+-spec query(MatcherName :: string(), Keys :: binary() | rctx_field() | [binary()] | [rctx_field()]) ->
+ {ok, query_result()}
| {error, any()}.
-query(Keys) ->
- csrt_query:query(Keys).
-
-%% #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}
-query(Keys, Options) ->
- csrt_query:query(Keys, Options).
+query(MatcherName, AggregationKeys) ->
+ csrt_query:query(MatcherName, AggregationKeys).
+
+-spec query(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
+query(MatcherName, AggregationKeys, ValueKey, Options) ->
+ csrt_query:query(MatcherName, AggregationKeys, ValueKey, Options).
sorted(Map) ->
csrt_query:sorted(Map).
diff --git a/src/couch_stats/src/csrt_query.erl b/src/couch_stats/src/csrt_query.erl
index b461fedcb..75536c85d 100644
--- a/src/couch_stats/src/csrt_query.erl
+++ b/src/couch_stats/src/csrt_query.erl
@@ -12,6 +12,8 @@
-module(csrt_query).
+-feature(maybe_expr, enable).
+
-include_lib("stdlib/include/ms_transform.hrl").
-include_lib("couch_stats_resource_tracker.hrl").
@@ -32,8 +34,8 @@
find_workers_by_pidref/1,
group_by/3,
group_by/4,
- query/1,
query/2,
+ query/4,
query_matcher/1,
query_matcher/2,
query_matcher_rows/1,
@@ -270,11 +272,11 @@ query_matcher(MatcherName) when is_list(MatcherName) ->
-spec query_matcher(MatcherName :: matcher_name(), Limit :: pos_integer()) -> {ok, query_result()}
| {error, any()}.
query_matcher(MatcherName, Limit) when is_list(MatcherName) andalso is_integer(Limit) ->
- case csrt_logger:get_matcher(MatcherName) of
- undefined ->
- {error, {unknown_matcher, MatcherName}};
- Matcher ->
- query_matcher_rows(Matcher, Limit)
+ case get_matcher(MatcherName) of
+ {ok, Matcher} ->
+ query_matcher_rows(Matcher, Limit);
+ Error ->
+ Error
end.
-spec query_matcher_rows(Matcher :: matcher()) -> {ok, query_result()}
@@ -302,17 +304,90 @@ query_matcher_rows({MSpec, _CompMSpec}, Limit) when is_list(MSpec) andalso is_in
{error, Error}
end.
--spec query(Keys :: string() | [string()]) -> {ok, query_result()}
- | {error, any()}.
-%% #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}
-query(Keys) ->
- query(Keys, []).
+get_matcher(MatcherName) ->
+ case csrt_logger:get_matcher(MatcherName) of
+ undefined ->
+ {error, {unknown_matcher, MatcherName}};
+ Matcher ->
+ {ok, Matcher}
+ end.
--spec query(Keys :: string() | [string()], Options :: query_options()) -> {ok, query_result()}
+-spec query(MatcherName :: string(), Keys :: binary() | rctx_field() | [binary()] | [rctx_field()]) ->
+ {ok, query_result()}
| {error, any()}.
-%% #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}
-query(_Keys, _Options) ->
- {error, todo}.
+%% {ok, #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}}
+query(MatcherName, AggregationKeys) ->
+ query(MatcherName, AggregationKeys, undefined, #{}).
+
+-spec query(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
+%% {ok, #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}}
+query(MatcherName, AggregationKeys, ValueKey, Options) ->
+ AggregationKey = parse_key(AggregationKeys),
+ VKey = parse_key(ValueKey),
+ Limit = maps:get(Options, aggregation, query_limit()),
+ Aggregation = maps:get(Options, aggregation, none),
+ maybe
+ ok ?= validate_limit(Limit),
+ ok ?= validate_aggregation(Aggregation),
+ {ok, Matcher} ?= get_matcher(MatcherName),
+ case Aggregation of
+ group_by ->
+ group_by(Matcher, AggregationKey, VKey);
+ sort_by ->
+ sort_by(Matcher, AggregationKey, VKey);
+ count_by when VKey == undefined ->
+ count_by(Matcher, AggregationKey);
+ count_by ->
+ {error, {extra_argument, value_key}};
+ none ->
+ query_matcher_rows(Matcher, Limit)
+ end
+ end.
query_limit() ->
config:get_integer(?CSRT, "query_limit", ?QUERY_LIMIT).
+
+validate_limit(Limit) when is_integer(Limit) ->
+ case Limit =< query_limit() of
+ true ->
+ ok;
+ false ->
+ {error, {beyond_limit, query_limit()}}
+ end;
+validate_limit(Limit) ->
+ {error, {invalid_limit, Limit}}.
+
+validate_aggregation(none) ->
+ ok;
+validate_aggregation(group_by) ->
+ ok;
+validate_aggregation(sort_by) ->
+ ok;
+validate_aggregation(count_by) ->
+ ok;
+validate_aggregation(Other) ->
+ {error, {invalid_aggregation, Other}}.
+
+-spec parse_key(Keys :: binary() | atom() | [binary()] | [atom()]) ->
+ [rctx_field()]
+ | throw({bad_request, Reason :: binary()}).
+
+parse_key(Keys) when is_list(Keys) ->
+ parse_key(Keys, []);
+parse_key(BinKey) when is_binary(BinKey) ->
+ csrt_entry:key(BinKey);
+parse_key(undefined) ->
+ undefined;
+parse_key(Key) when is_atom(Key) ->
+ csrt_entry:key(Key).
+
+parse_key([BinKey | Rest], Keys) ->
+ parse_key(Rest, [csrt_entry:key(BinKey) | Keys]);
+parse_key([], Keys) ->
+ lists:reverse(Keys).