forked from elastic/elasticsearch
/
Params.java
127 lines (105 loc) · 3.9 KB
/
Params.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.expression.gen.script;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static java.util.Collections.emptyList;
/**
* Parameters for a script
*
* This class mainly exists to handle the different aggregation cases.
* While aggs can appear in scripts like regular parameters, they are not passed
* as parameters but rather as bucket_path.
* However in some cases (like count), it's not the agg path that is relevant but rather
* its property (_count).
* As the agg name still needs to be remembered to properly associate the script with.
*
* Hence why this class supports aggRef (which always returns the agg names) and aggPaths
* (which returns the agg property if it exists or the agg name/reference).
*
* Also the parameter names support late binding/evaluation since the agg reference (like function id)
* can be changed during the optimization phase (for example min agg -> stats.min).
*/
public class Params {
public static final Params EMPTY = new Params(emptyList());
private final List<Param<?>> params;
Params(List<Param<?>> params) {
// flatten params
this.params = flatten(params);
}
// return vars and aggs in the declared order for binding them to the script
List<String> asCodeNames() {
if (params.isEmpty()) {
return emptyList();
}
List<String> names = new ArrayList<>(params.size());
int aggs = 0, vars = 0;
for (Param<?> p : params) {
names.add(p.prefix() + (p instanceof Agg ? aggs++ : vars++));
}
return names;
}
// return only the vars (as parameter for a script)
// agg refs are returned separately to be provided as bucket_paths
Map<String, Object> asParams() {
Map<String, Object> map = new LinkedHashMap<>(params.size());
int count = 0;
for (Param<?> p : params) {
if (p instanceof Var) {
map.put(p.prefix() + count++, p.value());
}
}
return map;
}
// return agg refs in a format suitable for bucket_paths
Map<String, String> asAggPaths() {
Map<String, String> map = new LinkedHashMap<>();
int aggs = 0;
for (Param<?> p : params) {
if (p instanceof Agg) {
Agg a = (Agg) p;
String s = a.aggProperty() != null ? a.aggProperty() : a.aggName();
map.put(p.prefix() + aggs++, s);
}
if (p instanceof Grouping) {
Grouping g = (Grouping) p;
map.put(p.prefix() + aggs++, g.groupName());
}
}
return map;
}
private static List<Param<?>> flatten(List<Param<?>> params) {
List<Param<?>> flatten = emptyList();
if (!params.isEmpty()) {
flatten = new ArrayList<>();
for (Param<?> p : params) {
if (p instanceof Script) {
flatten.addAll(flatten(((Script) p).value().params));
}
else if (p instanceof Agg) {
flatten.add(p);
}
else if (p instanceof Grouping) {
flatten.add(p);
}
else if (p instanceof Var) {
flatten.add(p);
}
else {
throw new SqlIllegalArgumentException("Unsupported field {}", p);
}
}
}
return flatten;
}
@Override
public String toString() {
return params.toString();
}
}