Skip to content

Commit 1b179e5

Browse files
ES|QL: Disallow brackets in unquoted index patterns
1 parent 16458de commit 1b179e5

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,13 @@ public enum Cap {
12151215
/**
12161216
* (Re)Added EXPLAIN command
12171217
*/
1218-
EXPLAIN(Build.current().isSnapshot());
1218+
EXPLAIN(Build.current().isSnapshot()),
1219+
1220+
/**
1221+
* Forbid usage of brackets in unquoted index and enrich policy names
1222+
* https://github.com/elastic/elasticsearch/issues/130378
1223+
*/
1224+
NO_BRACKETS_IN_UNQUOTED_INDEX_NAMES;
12191225

12201226
private final boolean enabled;
12211227

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4739,4 +4739,27 @@ public void testUnclosedParenthesis() {
47394739
expectError(q, "Invalid query");
47404740
}
47414741
}
4742+
4743+
public void testBracketsInIndexNames() {
4744+
expectError("from test)", "line 1:10: extraneous input ')' expecting <EOF>");
4745+
4746+
expectError("from test | enrich foo)", "line -1:-1: Invalid query [from test | enrich foo)]");
4747+
4748+
expectError("from test | lookup join foo) on bar", "line 1:28: token recognition error at: ')'");
4749+
4750+
LogicalPlan plan = statement("from \"test)\"");
4751+
UnresolvedRelation from = as(plan, UnresolvedRelation.class);
4752+
assertThat(from.indexPattern().indexPattern(), is("test)"));
4753+
4754+
plan = statement("from test | enrich \"foo)\"");
4755+
Enrich enrich = as(plan, Enrich.class);
4756+
assertThat(enrich.policyName().fold(FoldContext.small()), is(BytesRefs.toBytesRef("foo)")));
4757+
as(enrich.child(), UnresolvedRelation.class);
4758+
4759+
plan = statement("from test | lookup join \"foo)\" on bar");
4760+
LookupJoin lookup = as(plan, LookupJoin.class);
4761+
UnresolvedRelation right = as(lookup.right(), UnresolvedRelation.class);
4762+
assertThat(right.indexPattern().indexPattern(), is("foo)"));
4763+
}
4764+
47424765
}

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/220_explain.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,29 @@ explainQuery:
8686
- match: { values.2.0: "coordinator" }
8787
- match: { values.2.1: "optimizedPhysicalPlan" }
8888

89+
---
90+
explainFrom:
91+
- do:
92+
allowed_warnings_regex:
93+
- "No limit defined, adding default limit of \\[.*\\]"
94+
esql.query:
95+
body:
96+
query: 'EXPLAIN (from test)'
97+
98+
- length: { columns: 3 }
99+
- match: {columns.0.name: "role"}
100+
- match: {columns.0.type: "keyword"}
101+
- match: {columns.1.name: "type"}
102+
- match: {columns.1.type: "keyword"}
103+
- match: {columns.2.name: "plan"}
104+
- match: {columns.2.type: "keyword"}
105+
- length: { values: 3 }
106+
- match: { values.0.0: "coordinator" }
107+
- match: { values.0.1: "parsedPlan" }
108+
- match: { values.1.0: "coordinator" }
109+
- match: { values.1.1: "optimizedLogicalPlan" }
110+
- match: { values.2.0: "coordinator" }
111+
- match: { values.2.1: "optimizedPhysicalPlan" }
89112

90113
---
91114
explainDownstream:

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_enrich.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,59 @@ teardown:
191191
- match: { values.1: [ "Bob", "New York", "nyc", "USA" ] }
192192
- match: { values.2: [ "Denise", "Tan Son Nhat", null, null ] }
193193
- match: { values.3: [ "Mario", "Rome", "rom", "Italy" ] }
194+
195+
196+
---
197+
"Enrich with brackets in policy name":
198+
- requires:
199+
test_runner_features: [capabilities, allowed_warnings_regex]
200+
capabilities:
201+
- method: POST
202+
path: /_query
203+
parameters: []
204+
capabilities: [ no_brackets_in_unquoted_index_names ]
205+
reason: "Change in the grammar"
206+
207+
- do:
208+
allowed_warnings_regex:
209+
- "No limit defined, adding default limit of \\[.*\\]"
210+
esql.query:
211+
body:
212+
query: 'from test | enrich "city_codes_policy)" on city_id | keep name, city, country | sort name'
213+
catch: "bad_request"
214+
215+
- match: { status: 400 }
216+
- match: { error.type: verification_exception }
217+
- match: { error.reason: "/.*cannot.find.enrich.policy.*/" }
218+
219+
220+
---
221+
"Enrich in fork":
222+
- requires:
223+
test_runner_features: [capabilities, allowed_warnings_regex]
224+
capabilities:
225+
- method: POST
226+
path: /_query
227+
parameters: []
228+
capabilities: [ no_brackets_in_unquoted_index_names ]
229+
reason: "Change in the grammar"
230+
231+
- do:
232+
allowed_warnings_regex:
233+
- "No limit defined, adding default limit of \\[.*\\]"
234+
esql.query:
235+
body:
236+
query: 'from test | eval city_code = city_id | FORK (enrich city_codes_policy) (where false) | keep name, city, country | sort name'
237+
238+
- match: { columns.0.name: "name" }
239+
- match: { columns.0.type: "keyword" }
240+
- match: { columns.1.name: "city" }
241+
- match: { columns.1.type: "text" }
242+
- match: { columns.2.name: "country" }
243+
- match: { columns.2.type: "keyword" }
244+
245+
- length: { values: 4 }
246+
- match: { values.0: [ "Alice", "New York", "USA" ] }
247+
- match: { values.1: [ "Bob", "New York", "USA" ] }
248+
- match: { values.2: [ "Denise", null, null ] }
249+
- match: { values.3: [ "Mario", "Rome", "Italy" ] }

0 commit comments

Comments
 (0)