Skip to content

Commit 62e8906

Browse files
authored
Merge branch 'main' into mtv24
2 parents ccd4e13 + 02a519a commit 62e8906

File tree

8 files changed

+518
-57
lines changed

8 files changed

+518
-57
lines changed
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.
22

33
```esql
4-
ROW i=1, a=["a", "b"], b=[2, 3] | STATS MIN(i) BY a, b | SORT a ASC, b ASC
4+
ROW price = 10, color = ["blue", "pink", "yellow"], size = ["s", "m", "l"]
5+
| STATS SUM(price) BY color, size
56
```
67

7-
| MIN(i):integer | a:keyword | b:integer |
8+
| SUM(price):long | color:keyword | size:keyword |
89
| --- | --- | --- |
9-
| 1 | a | 2 |
10-
| 1 | a | 3 |
11-
| 1 | b | 2 |
12-
| 1 | b | 3 |
10+
| 10 | blue | l |
11+
| 10 | blue | m |
12+
| 10 | blue | s |
13+
| 10 | pink | l |
14+
| 10 | pink | m |
15+
| 10 | pink | s |
16+
| 10 | yellow | l |
17+
| 10 | yellow | m |
18+
| 10 | yellow | s |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.
2+
3+
```esql
4+
ROW color = ["blue", "pink", "yellow"]
5+
| MV_EXPAND color
6+
| STATS VALUES(color) BY color
7+
```
8+
9+
| VALUES(color):keyword | color:keyword |
10+
| --- | --- |
11+
| blue | blue |
12+
| pink | pink |
13+
| yellow | yellow |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.
2+
3+
```esql
4+
ROW color = ["blue", "pink", "yellow"]
5+
| STATS VALUES(color) BY color
6+
```
7+
8+
| VALUES(color):keyword | color:keyword |
9+
| --- | --- |
10+
| [blue, pink, yellow] | blue |
11+
| [blue, pink, yellow] | pink |
12+
| [blue, pink, yellow] | yellow |
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.
22

33
```esql
4-
ROW i=1, a=["a", "b"] | STATS MIN(i) BY a | SORT a ASC
4+
ROW price = 10, color = ["blue", "pink", "yellow"]
5+
| STATS SUM(price) BY color
56
```
67

7-
| MIN(i):integer | a:keyword |
8+
| SUM(price):long | color:keyword |
89
| --- | --- |
9-
| 1 | a |
10-
| 1 | b |
10+
| 10 | blue |
11+
| 10 | pink |
12+
| 10 | yellow |

docs/reference/query-languages/esql/_snippets/commands/layout/stats-by.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,24 @@ It’s also possible to group by multiple values:
110110

111111
:::{include} ../examples/stats.csv-spec/statsGroupByMultipleValues.md
112112
:::
113+
113114
If all the grouping keys are multivalued then the input row is in all groups:
114115

115116
:::{include} ../examples/stats.csv-spec/multi-mv-group.md
116117
:::
117118

119+
The input **ROW** is in all groups. The entire row. All the values. Even group
120+
keys. That means that:
121+
122+
:::{include} ../examples/stats.csv-spec/mv-group-values.md
123+
:::
124+
125+
The `VALUES` function above sees the whole row - all of the values of the group
126+
key. If you want to send the group key to the function then `MV_EXPAND` first:
127+
128+
:::{include} ../examples/stats.csv-spec/mv-group-values-expand.md
129+
:::
130+
118131
Both the aggregating functions and the grouping expressions accept other
119132
functions. This is useful for using `STATS` on multivalue columns.
120133
For example, to calculate the average salary change, you can use `MV_AVG` to

x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,34 +2299,6 @@ M
22992299
null
23002300
;
23012301

2302-
docsStatsMvGroup
2303-
// tag::mv-group[]
2304-
ROW i=1, a=["a", "b"] | STATS MIN(i) BY a | SORT a ASC
2305-
// end::mv-group[]
2306-
;
2307-
2308-
// tag::mv-group-result[]
2309-
MIN(i):integer | a:keyword
2310-
1 | a
2311-
1 | b
2312-
// end::mv-group-result[]
2313-
;
2314-
2315-
docsStatsMultiMvGroup
2316-
// tag::multi-mv-group[]
2317-
ROW i=1, a=["a", "b"], b=[2, 3] | STATS MIN(i) BY a, b | SORT a ASC, b ASC
2318-
// end::multi-mv-group[]
2319-
;
2320-
2321-
// tag::multi-mv-group-result[]
2322-
MIN(i):integer | a:keyword | b:integer
2323-
1 | a | 2
2324-
1 | a | 3
2325-
1 | b | 2
2326-
1 | b | 3
2327-
// end::multi-mv-group-result[]
2328-
;
2329-
23302302
statsByConstant#[skip:-8.14.1,reason:implemented in 8.14]
23312303
from employees
23322304
| stats m = max(salary), a = round(avg(salary)) by 0
@@ -3338,3 +3310,74 @@ FROM employees
33383310
min1:integer | min2:integer | max1:integer | max2:integer
33393311
10011 | [10011, 10012] | 10079 | [10079, 10078]
33403312
;
3313+
3314+
sumRowMany
3315+
// tag::mv-group[]
3316+
ROW price = 10, color = ["blue", "pink", "yellow"]
3317+
| STATS SUM(price) BY color
3318+
// end::mv-group[]
3319+
| SORT color ASC
3320+
;
3321+
3322+
// tag::mv-group-result[]
3323+
SUM(price):long | color:keyword
3324+
10 | blue
3325+
10 | pink
3326+
10 | yellow
3327+
// end::mv-group-result[]
3328+
;
3329+
3330+
sumRowManyTwo
3331+
// tag::multi-mv-group[]
3332+
ROW price = 10, color = ["blue", "pink", "yellow"], size = ["s", "m", "l"]
3333+
| STATS SUM(price) BY color, size
3334+
// end::multi-mv-group[]
3335+
| SORT color ASC, size ASC
3336+
;
3337+
3338+
// tag::multi-mv-group-result[]
3339+
SUM(price):long | color:keyword | size:keyword
3340+
10 | blue | l
3341+
10 | blue | m
3342+
10 | blue | s
3343+
10 | pink | l
3344+
10 | pink | m
3345+
10 | pink | s
3346+
10 | yellow | l
3347+
10 | yellow | m
3348+
10 | yellow | s
3349+
// end::multi-mv-group-result[]
3350+
;
3351+
3352+
valuesRowMany
3353+
// tag::mv-group-values[]
3354+
ROW color = ["blue", "pink", "yellow"]
3355+
| STATS VALUES(color) BY color
3356+
// end::mv-group-values[]
3357+
| SORT color ASC
3358+
;
3359+
3360+
// tag::mv-group-values-result[]
3361+
VALUES(color):keyword | color:keyword
3362+
[blue, pink, yellow] | blue
3363+
[blue, pink, yellow] | pink
3364+
[blue, pink, yellow] | yellow
3365+
// end::mv-group-values-result[]
3366+
;
3367+
3368+
valuesRowManyExpand
3369+
// tag::mv-group-values-expand[]
3370+
ROW color = ["blue", "pink", "yellow"]
3371+
| MV_EXPAND color
3372+
| STATS VALUES(color) BY color
3373+
// end::mv-group-values-expand[]
3374+
| SORT color ASC
3375+
;
3376+
3377+
// tag::mv-group-values-expand-result[]
3378+
VALUES(color):keyword | color:keyword
3379+
blue | blue
3380+
pink | pink
3381+
yellow | yellow
3382+
// end::mv-group-values-expand-result[]
3383+
;

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/PluggableAuthenticatorChain.java

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,26 @@
77

88
package org.elasticsearch.xpack.security.authc;
99

10+
import org.apache.logging.log4j.LogManager;
11+
import org.apache.logging.log4j.Logger;
1012
import org.elasticsearch.action.ActionListener;
13+
import org.elasticsearch.xpack.core.common.IteratingActionListener;
1114
import org.elasticsearch.xpack.core.security.authc.Authentication;
1215
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
1316
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
1417
import org.elasticsearch.xpack.core.security.authc.CustomAuthenticator;
1518

1619
import java.util.Collections;
1720
import java.util.List;
21+
import java.util.function.BiConsumer;
22+
import java.util.function.Function;
23+
24+
import static org.elasticsearch.common.Strings.format;
1825

1926
public class PluggableAuthenticatorChain implements Authenticator {
2027

28+
private static final Logger logger = LogManager.getLogger(PluggableAuthenticatorChain.class);
29+
2130
private final List<CustomAuthenticator> customAuthenticators;
2231

2332
public PluggableAuthenticatorChain(List<CustomAuthenticator> customAuthenticators) {
@@ -59,28 +68,47 @@ public void authenticate(Context context, ActionListener<AuthenticationResult<Au
5968
}
6069
AuthenticationToken token = context.getMostRecentAuthenticationToken();
6170
if (token != null) {
62-
// TODO switch to IteratingActionListener
63-
for (CustomAuthenticator customAuthenticator : customAuthenticators) {
64-
if (customAuthenticator.supports(token)) {
65-
customAuthenticator.authenticate(token, ActionListener.wrap(response -> {
66-
if (response.isAuthenticated()) {
67-
listener.onResponse(response);
68-
} else if (response.getStatus() == AuthenticationResult.Status.TERMINATE) {
69-
final Exception ex = response.getException();
70-
if (ex == null) {
71-
listener.onFailure(context.getRequest().authenticationFailed(token));
72-
} else {
73-
listener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token));
74-
}
75-
} else if (response.getStatus() == AuthenticationResult.Status.CONTINUE) {
76-
listener.onResponse(AuthenticationResult.notHandled());
77-
}
78-
}, ex -> listener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token))));
79-
return;
80-
}
71+
var iteratingListener = new IteratingActionListener<>(
72+
listener,
73+
getAuthConsumer(context),
74+
customAuthenticators,
75+
context.getThreadContext(),
76+
Function.identity(),
77+
result -> result.getStatus() == AuthenticationResult.Status.CONTINUE
78+
);
79+
try {
80+
iteratingListener.run();
81+
} catch (Exception e) {
82+
logger.debug(() -> format("Authentication of token [%s] failed", token.getClass().getName()), e);
83+
listener.onFailure(context.getRequest().exceptionProcessingRequest(e, token));
8184
}
85+
return;
8286
}
8387
listener.onResponse(AuthenticationResult.notHandled());
8488
}
8589

90+
private BiConsumer<CustomAuthenticator, ActionListener<AuthenticationResult<Authentication>>> getAuthConsumer(Context context) {
91+
AuthenticationToken token = context.getMostRecentAuthenticationToken();
92+
return (authenticator, iteratingListener) -> {
93+
if (authenticator.supports(token)) {
94+
authenticator.authenticate(token, ActionListener.wrap(response -> {
95+
if (response.isAuthenticated()) {
96+
iteratingListener.onResponse(response);
97+
} else if (response.getStatus() == AuthenticationResult.Status.TERMINATE) {
98+
final Exception ex = response.getException();
99+
if (ex == null) {
100+
iteratingListener.onFailure(context.getRequest().authenticationFailed(token));
101+
} else {
102+
iteratingListener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token));
103+
}
104+
} else if (response.getStatus() == AuthenticationResult.Status.CONTINUE) {
105+
iteratingListener.onResponse(AuthenticationResult.notHandled());
106+
}
107+
}, ex -> iteratingListener.onFailure(context.getRequest().exceptionProcessingRequest(ex, token))));
108+
} else {
109+
iteratingListener.onResponse(AuthenticationResult.notHandled()); // try the next custom authenticator
110+
}
111+
};
112+
}
113+
86114
}

0 commit comments

Comments
 (0)