Skip to content

Commit 6261090

Browse files
Merge branch 'main' into esql/fix_131028
2 parents 6469722 + a436dbe commit 6261090

File tree

5 files changed

+159
-23
lines changed

5 files changed

+159
-23
lines changed

docs/changelog/130427.yaml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
pr: 130427
2-
summary: Disallow brackets in unquoted index pattersn
2+
summary: Disallow brackets in unquoted index patterns
33
area: ES|QL
4-
type: bug
5-
issues: []
4+
type: breaking
5+
issues:
6+
- 130378
7+
breaking:
8+
title: Unquoted index patterns do not allow `(` and `)` characters
9+
area: ES|QL
10+
details: >-
11+
Previously, ES|QL accepted unquoted index patterns containing brackets, such as `FROM index(1) | ENRICH policy(2)`.
12+
13+
This query syntax is no longer valid because it could conflict with subquery syntax, where brackets are used as delimiters.
14+
15+
Brackets are now only allowed in quoted index patterns. For example: `FROM "index(1)" | ENRICH "policy(2)"`.
16+
impact: "This affects existing queries containing brackets in index or policy names, i.e. in FROM, ENRICH, and LOOKUP JOIN commands."
17+
notable: false

modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexBasicTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.Map;
2424
import java.util.stream.Collectors;
2525

26+
import static org.elasticsearch.index.IndexSettings.SYNTHETIC_VECTORS;
2627
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
2728
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
2829
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
@@ -181,6 +182,7 @@ public void testReindexFromComplexDateMathIndexName() throws Exception {
181182
}
182183

183184
public void testReindexIncludeVectors() throws Exception {
185+
assumeTrue("This test requires synthetic vectors to be enabled", SYNTHETIC_VECTORS);
184186
var resp1 = prepareCreate("test").setSettings(
185187
Settings.builder().put(IndexSettings.INDEX_MAPPING_SOURCE_SYNTHETIC_VECTORS_SETTING.getKey(), true).build()
186188
).setMapping("foo", "type=dense_vector,similarity=l2_norm", "bar", "type=sparse_vector").get();

modules/reindex/src/test/java/org/elasticsearch/reindex/UpdateByQueryBasicTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Map;
2525
import java.util.stream.Collectors;
2626

27+
import static org.elasticsearch.index.IndexSettings.SYNTHETIC_VECTORS;
2728
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
2829
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
2930
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
@@ -157,6 +158,7 @@ public void testMissingSources() {
157158
}
158159

159160
public void testUpdateByQueryIncludeVectors() throws Exception {
161+
assumeTrue("This test requires synthetic vectors to be enabled", SYNTHETIC_VECTORS);
160162
var resp1 = prepareCreate("test").setSettings(
161163
Settings.builder().put(IndexSettings.INDEX_MAPPING_SOURCE_SYNTHETIC_VECTORS_SETTING.getKey(), true).build()
162164
).setMapping("foo", "type=dense_vector,similarity=l2_norm", "bar", "type=sparse_vector").get();

server/src/main/java/org/elasticsearch/tasks/TaskManager.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,33 @@ public Task register(String type, String action, TaskAwareRequest request, boole
170170
Task previousTask = tasks.put(task.getId(), task);
171171
assert previousTask == null;
172172
if (traceRequest) {
173-
startTrace(threadContext, task);
173+
maybeStartTrace(threadContext, task);
174174
}
175175
}
176176
return task;
177177
}
178178

179-
// package private for testing
180-
void startTrace(ThreadContext threadContext, Task task) {
179+
/**
180+
* Start a new trace span if a parent trace context already exists.
181+
* For REST actions this will be the case, otherwise {@link Tracer#startTrace} can be used.
182+
*/
183+
void maybeStartTrace(ThreadContext threadContext, Task task) {
184+
if (threadContext.hasParentTraceContext() == false) {
185+
return;
186+
}
181187
TaskId parentTask = task.getParentTaskId();
182188
Map<String, Object> attributes = parentTask.isSet()
183189
? Map.of(Tracer.AttributeKeys.TASK_ID, task.getId(), Tracer.AttributeKeys.PARENT_TASK_ID, parentTask.toString())
184190
: Map.of(Tracer.AttributeKeys.TASK_ID, task.getId());
185191
tracer.startTrace(threadContext, task, task.getAction(), attributes);
186192
}
187193

194+
void maybeStopTrace(ThreadContext threadContext, Task task) {
195+
if (threadContext.hasTraceContext()) {
196+
tracer.stopTrace(task);
197+
}
198+
}
199+
188200
public <Request extends ActionRequest, Response extends ActionResponse> Task registerAndExecute(
189201
String type,
190202
TransportAction<Request, Response> action,
@@ -247,7 +259,7 @@ private void registerCancellableTask(Task task, long requestId, boolean traceReq
247259
CancellableTaskHolder holder = new CancellableTaskHolder(cancellableTask);
248260
cancellableTasks.put(task, requestId, holder);
249261
if (traceRequest) {
250-
startTrace(threadPool.getThreadContext(), task);
262+
maybeStartTrace(threadPool.getThreadContext(), task);
251263
}
252264
// Check if this task was banned before we start it.
253265
if (task.getParentTaskId().isSet()) {
@@ -346,7 +358,7 @@ public Task unregister(Task task) {
346358
return removedTask;
347359
}
348360
} finally {
349-
tracer.stopTrace(task);
361+
maybeStopTrace(threadPool.getThreadContext(), task);
350362
for (RemovedTaskListener listener : removedTaskListeners) {
351363
listener.onRemoved(task);
352364
}

server/src/test/java/org/elasticsearch/tasks/TaskManagerTests.java

Lines changed: 123 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import static org.mockito.Mockito.spy;
6969
import static org.mockito.Mockito.times;
7070
import static org.mockito.Mockito.verify;
71+
import static org.mockito.Mockito.verifyNoInteractions;
7172
import static org.mockito.Mockito.when;
7273

7374
public class TaskManagerTests extends ESTestCase {
@@ -281,13 +282,72 @@ public void testTaskAccounting() {
281282
/**
282283
* Check that registering a task also causes tracing to be started on that task.
283284
*/
284-
public void testRegisterTaskStartsTracing() {
285+
public void testRegisterTaskStartsTracingIfTraceParentExists() {
285286
final Tracer mockTracer = mock(Tracer.class);
286287
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
287288

289+
// fake a trace parent
290+
threadPool.getThreadContext().putHeader(Task.TRACE_PARENT_HTTP_HEADER, "traceparent");
288291
final boolean hasParentTask = randomBoolean();
289292
final TaskId parentTask = hasParentTask ? new TaskId("parentNode", 1) : TaskId.EMPTY_TASK_ID;
290293

294+
try (var ignored = threadPool.getThreadContext().newTraceContext()) {
295+
296+
final Task task = taskManager.register("testType", "testAction", new TaskAwareRequest() {
297+
298+
@Override
299+
public void setParentTask(TaskId taskId) {}
300+
301+
@Override
302+
public void setRequestId(long requestId) {}
303+
304+
@Override
305+
public TaskId getParentTask() {
306+
return parentTask;
307+
}
308+
});
309+
310+
Map<String, Object> attributes = hasParentTask
311+
? Map.of(Tracer.AttributeKeys.TASK_ID, task.getId(), Tracer.AttributeKeys.PARENT_TASK_ID, parentTask.toString())
312+
: Map.of(Tracer.AttributeKeys.TASK_ID, task.getId());
313+
verify(mockTracer).startTrace(any(), eq(task), eq("testAction"), eq(attributes));
314+
}
315+
}
316+
317+
/**
318+
* Check that registering a task also causes tracing to be started on that task.
319+
*/
320+
public void testRegisterTaskSkipsTracingIfTraceParentMissing() {
321+
final Tracer mockTracer = mock(Tracer.class);
322+
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
323+
324+
// no trace parent
325+
try (var ignored = threadPool.getThreadContext().newTraceContext()) {
326+
final Task task = taskManager.register("testType", "testAction", new TaskAwareRequest() {
327+
328+
@Override
329+
public void setParentTask(TaskId taskId) {}
330+
331+
@Override
332+
public void setRequestId(long requestId) {}
333+
334+
@Override
335+
public TaskId getParentTask() {
336+
return TaskId.EMPTY_TASK_ID;
337+
}
338+
});
339+
}
340+
341+
verifyNoInteractions(mockTracer);
342+
}
343+
344+
/**
345+
* Check that unregistering a task also causes tracing to be stopped on that task.
346+
*/
347+
public void testUnregisterTaskStopsTracingIfTraceContextExists() {
348+
final Tracer mockTracer = mock(Tracer.class);
349+
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
350+
291351
final Task task = taskManager.register("testType", "testAction", new TaskAwareRequest() {
292352

293353
@Override
@@ -298,20 +358,21 @@ public void setRequestId(long requestId) {}
298358

299359
@Override
300360
public TaskId getParentTask() {
301-
return parentTask;
361+
return TaskId.EMPTY_TASK_ID;
302362
}
303363
});
304364

305-
Map<String, Object> attributes = hasParentTask
306-
? Map.of(Tracer.AttributeKeys.TASK_ID, task.getId(), Tracer.AttributeKeys.PARENT_TASK_ID, parentTask.toString())
307-
: Map.of(Tracer.AttributeKeys.TASK_ID, task.getId());
308-
verify(mockTracer).startTrace(any(), eq(task), eq("testAction"), eq(attributes));
365+
// fake a trace context (trace parent)
366+
threadPool.getThreadContext().putHeader(Task.TRACE_PARENT_HTTP_HEADER, "traceparent");
367+
368+
taskManager.unregister(task);
369+
verify(mockTracer).stopTrace(task);
309370
}
310371

311372
/**
312373
* Check that unregistering a task also causes tracing to be stopped on that task.
313374
*/
314-
public void testUnregisterTaskStopsTracing() {
375+
public void testUnregisterTaskStopsTracingIfTraceContextMissing() {
315376
final Tracer mockTracer = mock(Tracer.class);
316377
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
317378

@@ -329,18 +390,22 @@ public TaskId getParentTask() {
329390
}
330391
});
331392

332-
taskManager.unregister(task);
393+
// no trace context
333394

334-
verify(mockTracer).stopTrace(task);
395+
taskManager.unregister(task);
396+
verifyNoInteractions(mockTracer);
335397
}
336398

337399
/**
338-
* Check that registering and executing a task also causes tracing to be started and stopped on that task.
400+
* Check that registering and executing a task also causes tracing to be started if a trace parent exists.
339401
*/
340-
public void testRegisterAndExecuteStartsAndStopsTracing() {
402+
public void testRegisterAndExecuteStartsTracingIfTraceParentExists() {
341403
final Tracer mockTracer = mock(Tracer.class);
342404
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
343405

406+
// fake a trace parent
407+
threadPool.getThreadContext().putHeader(Task.TRACE_PARENT_HTTP_HEADER, "traceparent");
408+
344409
final Task task = taskManager.registerAndExecute(
345410
"testType",
346411
new TransportAction<ActionRequest, ActionResponse>(
@@ -375,25 +440,68 @@ public TaskId getParentTask() {
375440
verify(mockTracer).startTrace(any(), eq(task), eq("actionName"), anyMap());
376441
}
377442

443+
/**
444+
* Check that registering and executing a task skips tracing if trace parent does not exists.
445+
*/
446+
public void testRegisterAndExecuteSkipsTracingIfTraceParentMissing() {
447+
final Tracer mockTracer = mock(Tracer.class);
448+
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer);
449+
450+
// clean thread context without trace parent
451+
452+
final Task task = taskManager.registerAndExecute(
453+
"testType",
454+
new TransportAction<ActionRequest, ActionResponse>(
455+
"actionName",
456+
new ActionFilters(Set.of()),
457+
taskManager,
458+
EsExecutors.DIRECT_EXECUTOR_SERVICE
459+
) {
460+
@Override
461+
protected void doExecute(Task task, ActionRequest request, ActionListener<ActionResponse> listener) {
462+
listener.onResponse(new ActionResponse() {
463+
@Override
464+
public void writeTo(StreamOutput out) {}
465+
});
466+
}
467+
},
468+
new ActionRequest() {
469+
@Override
470+
public ActionRequestValidationException validate() {
471+
return null;
472+
}
473+
474+
@Override
475+
public TaskId getParentTask() {
476+
return TaskId.EMPTY_TASK_ID;
477+
}
478+
},
479+
null,
480+
ActionTestUtils.assertNoFailureListener(r -> {})
481+
);
482+
483+
verifyNoInteractions(mockTracer);
484+
}
485+
378486
public void testRegisterWithEnabledDisabledTracing() {
379487
final Tracer mockTracer = mock(Tracer.class);
380488
final TaskManager taskManager = spy(new TaskManager(Settings.EMPTY, threadPool, Set.of(), mockTracer));
381489

382490
taskManager.register("type", "action", makeTaskRequest(true, 123), false);
383-
verify(taskManager, times(0)).startTrace(any(), any());
491+
verify(taskManager, times(0)).maybeStartTrace(any(), any());
384492

385493
taskManager.register("type", "action", makeTaskRequest(false, 234), false);
386-
verify(taskManager, times(0)).startTrace(any(), any());
494+
verify(taskManager, times(0)).maybeStartTrace(any(), any());
387495

388496
clearInvocations(taskManager);
389497

390498
taskManager.register("type", "action", makeTaskRequest(true, 345), true);
391-
verify(taskManager, times(1)).startTrace(any(), any());
499+
verify(taskManager, times(1)).maybeStartTrace(any(), any());
392500

393501
clearInvocations(taskManager);
394502

395503
taskManager.register("type", "action", makeTaskRequest(false, 456), true);
396-
verify(taskManager, times(1)).startTrace(any(), any());
504+
verify(taskManager, times(1)).maybeStartTrace(any(), any());
397505
}
398506

399507
static class CancellableRequest extends AbstractTransportRequest {

0 commit comments

Comments
 (0)