Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
4b693fb
Adding ES|QL command URI_PART
eyalkoren Dec 26, 2025
3a92c2d
[CI] Auto commit changes from spotless
Dec 26, 2025
5bb2450
Fix yaml test to include new capability
eyalkoren Dec 27, 2025
0ec10eb
Merge remote-tracking branch 'eyalkoren/esql-uri_parts-command' into …
eyalkoren Dec 27, 2025
84172a6
Making UriPartsFunction a singleton
eyalkoren Dec 28, 2025
c39da7c
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Dec 28, 2025
b990cf1
Refix yaml test
eyalkoren Dec 28, 2025
34d8d16
[CI] Auto commit changes from spotless
Dec 28, 2025
6cd0eb3
Ensure consistent creation of UriParts and UriPartsExec
eyalkoren Dec 28, 2025
24c8e28
Merge remote-tracking branch 'eyalkoren/esql-uri_parts-command' into …
eyalkoren Dec 28, 2025
c1cce24
[CI] Auto commit changes from spotless
Dec 28, 2025
fac8358
Extending tests
eyalkoren Dec 28, 2025
318e57a
Workaround generative test failure through dataset changes
eyalkoren Dec 28, 2025
2f14092
Fix also dataset mappings
eyalkoren Dec 28, 2025
1950acc
Optimizing rules
eyalkoren Dec 28, 2025
7397c82
Adding unit tests for planning, analysis and optimizations
eyalkoren Dec 30, 2025
14c922e
Spotless
eyalkoren Dec 30, 2025
8117d21
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Dec 30, 2025
fecdf1c
Handling inconsistency between coordinating and data node
eyalkoren Jan 1, 2026
ceabffb
spotless
eyalkoren Jan 1, 2026
41a94df
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 1, 2026
0c36fe1
Fix tests
eyalkoren Jan 4, 2026
f835ef8
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 4, 2026
67998e9
Add serialization tests
eyalkoren Jan 5, 2026
3b881ff
Update docs/changelog/140004.yaml
eyalkoren Jan 5, 2026
58fd5b2
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 5, 2026
5c24bd0
Update docs/changelog/140004.yaml
eyalkoren Jan 8, 2026
38e0380
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 19, 2026
b33a887
Restoring regenerated ANTLR products
eyalkoren Jan 19, 2026
a3159b8
Restoring AnalyzerTests after merge
eyalkoren Jan 19, 2026
b5460c1
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 19, 2026
ea9ac7f
Making evaluation allocation-free and write directly to blocks
eyalkoren Jan 27, 2026
8f7d68d
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 28, 2026
fd22eed
Complete merge
eyalkoren Jan 28, 2026
2ed210f
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 28, 2026
d5215f2
Some fixes
eyalkoren Jan 28, 2026
c120466
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 28, 2026
8d8ffa2
Applying review comments
eyalkoren Jan 28, 2026
1a94463
Adding infrastructure for multi-value unit tests
eyalkoren Jan 29, 2026
9768d70
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 29, 2026
4e793e3
Adding approximation optimization support and test
eyalkoren Jan 29, 2026
b4c8ba3
Simplify row output evaluation
eyalkoren Jan 29, 2026
9ef68fa
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Jan 29, 2026
e9b9997
Add more csv test cases
eyalkoren Feb 1, 2026
5eb2ab6
Applying OperatorTestCase tests for AbstractCompoundOutputEvaluatorTests
eyalkoren Feb 2, 2026
c67ad86
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 2, 2026
d261373
Complete merge fixes
eyalkoren Feb 2, 2026
2cbfe74
Add docs
eyalkoren Feb 2, 2026
e2bd54c
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 2, 2026
4340112
Complete merge
eyalkoren Feb 2, 2026
7ec42eb
Adding to toc
eyalkoren Feb 3, 2026
3bf8574
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 3, 2026
d346fb4
Minimizing capability name
eyalkoren Feb 3, 2026
11fdd7e
Adding chicken to syntax description in docs
eyalkoren Feb 3, 2026
1dcd144
Making all compound output commands implement Streaming
eyalkoren Feb 3, 2026
d00d217
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 3, 2026
84f6dc5
Fix: creating a collector and RowOutput per evaluator instance
eyalkoren Feb 4, 2026
7d1bfab
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 4, 2026
654b75f
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 4, 2026
05b6e65
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 8, 2026
4ba1271
Applying some review comments
eyalkoren Feb 9, 2026
6880575
Refactor command name - enable on official builds
eyalkoren Feb 9, 2026
597e8b2
Adding requested csv tests
eyalkoren Feb 9, 2026
55d40e4
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 9, 2026
92a4626
Removing unused inport
eyalkoren Feb 9, 2026
3fc1184
Refactor to avoid hard coded warnings mode
eyalkoren Feb 10, 2026
479049f
Spotless
eyalkoren Feb 10, 2026
1360926
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 10, 2026
c15e691
Swtich to use UriParts logic from shared web-utils lib
eyalkoren Feb 10, 2026
dd057b2
Applying code review request
eyalkoren Feb 10, 2026
bb80e54
Applying review comments
eyalkoren Feb 10, 2026
8fc353e
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 10, 2026
0a49935
Switching to use SequenceBytesRefBlockSourceOperator
eyalkoren Feb 10, 2026
675e0f3
Merge branch 'main' into esql-uri_parts-command
eyalkoren Feb 11, 2026
9db6c5d
Merge branch 'main' into esql-uri_parts-command
eyalkoren Feb 11, 2026
5a84db8
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 15, 2026
3e3df4f
Complete merge
eyalkoren Feb 15, 2026
fd75ee9
[CI] Auto commit changes from spotless
Feb 15, 2026
bea8c40
Adding generative tests
eyalkoren Feb 15, 2026
6d4b01e
spotless
eyalkoren Feb 15, 2026
910b96f
Merge remote-tracking branch 'eyalkoren/esql-uri_parts-command' into …
eyalkoren Feb 15, 2026
0d856fa
Aligning generative test validation with other command generators
eyalkoren Feb 15, 2026
a924285
spotless
eyalkoren Feb 15, 2026
d86122c
Changing web-utils dependency to implementation
eyalkoren Feb 15, 2026
caca597
Publishing web-utils lib
eyalkoren Feb 16, 2026
1ec3af4
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 16, 2026
b1c2b45
Remove snapshot build feature flag
eyalkoren Feb 16, 2026
ebeae1a
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 16, 2026
a16bdba
Complete merge
eyalkoren Feb 16, 2026
d4be7b2
Fix 60_usage.yml test
eyalkoren Feb 16, 2026
fb6556f
Adding special sources to csv tests
eyalkoren Feb 17, 2026
ee224a9
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 17, 2026
2f3d4ec
Move mappings to new location
eyalkoren Feb 17, 2026
dc3fae2
Restoring strict generative test validation
eyalkoren Feb 17, 2026
35363ed
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 17, 2026
3e6b438
Fixing generative test framework and restoring even stricter validation
eyalkoren Feb 17, 2026
05b1647
[CI] Auto commit changes from spotless
Feb 17, 2026
332bf3e
Commenting out invalid column validation for LOOKUP_JOIN generative test
eyalkoren Feb 18, 2026
ae46d4f
Merge remote-tracking branch 'upstream/main' into esql-uri_parts-command
eyalkoren Feb 18, 2026
a1eb5b6
Remove dev-command leftover
eyalkoren Feb 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Adding generative tests
  • Loading branch information
eyalkoren committed Feb 15, 2026
commit bea8c40cf2407cd13b2c33c91d006ddf5f33ef5f
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.elasticsearch.xpack.esql.generator.command.pipe.SortGenerator;
import org.elasticsearch.xpack.esql.generator.command.pipe.StatsGenerator;
import org.elasticsearch.xpack.esql.generator.command.pipe.TimeSeriesStatsGenerator;
import org.elasticsearch.xpack.esql.generator.command.pipe.UriPartsGenerator;
import org.elasticsearch.xpack.esql.generator.command.pipe.WhereGenerator;
import org.elasticsearch.xpack.esql.generator.command.source.FromGenerator;
import org.elasticsearch.xpack.esql.generator.command.source.PromQLGenerator;
Expand Down Expand Up @@ -111,6 +112,7 @@ public class EsqlQueryGenerator {
SampleGenerator.INSTANCE,
SortGenerator.INSTANCE,
StatsGenerator.INSTANCE,
UriPartsGenerator.INSTANCE,
WhereGenerator.INSTANCE
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.esql.generator.command.pipe;

import org.elasticsearch.xpack.esql.core.type.DataType;
import org.elasticsearch.xpack.esql.evaluator.command.UriPartsFunctionBridge;
import org.elasticsearch.xpack.esql.generator.Column;
import org.elasticsearch.xpack.esql.generator.EsqlQueryGenerator;
import org.elasticsearch.xpack.esql.generator.QueryExecutor;
import org.elasticsearch.xpack.esql.generator.command.CommandGenerator;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.test.ESTestCase.randomBoolean;
import static org.elasticsearch.test.ESTestCase.randomFrom;

public class UriPartsGenerator implements CommandGenerator {

public static final CommandGenerator INSTANCE = new UriPartsGenerator();

public static final String URI_PARTS = "uri_parts";

/**
* Context key for the output field prefix (unquoted) used in the generated command.
*/
private static final String PREFIX = "prefix";

/**
* Expected URI_PARTS output field names and their ES|QL types. Computed once from
* {@link UriPartsFunctionBridge#getAllOutputFields()} and {@link DataType#fromJavaType}.
*/
private static final LinkedHashMap<String, String> URI_PARTS_OUTPUT_FIELDS;
static {
LinkedHashMap<String, Class<?>> outputFields = UriPartsFunctionBridge.getAllOutputFields();
URI_PARTS_OUTPUT_FIELDS = new LinkedHashMap<>(outputFields.size());
for (Map.Entry<String, Class<?>> e : outputFields.entrySet()) {
URI_PARTS_OUTPUT_FIELDS.putLast(e.getKey(), Objects.requireNonNull(DataType.fromJavaType(e.getValue())).typeName());
}
}

/**
* Valid literal URIs used so that at least some generated commands parse real URIs (happy path).
*/
private static final String[] LITERAL_URIS = new String[] {
"http://myusername:mypassword@www.example.com:80/foo.gif?key1=val1&key2=val2#fragment",
"https://www.elastic.co/downloads/elasticsearch",
"https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html",
"https://www.google.com/search?q=elasticsearch",
"https://github.com/elastic/elasticsearch",
"ftp://user:pass@files.internal/data.zip",
"/app/login?session=expired",
"/api/v1/users/123",
"https://www.example.com:8080/path?query=1#section" };

/**
* Column names that typically hold URI data (e.g. from web_logs). Prefer these when present.
*/
private static final Set<String> URI_LIKE_FIELD_NAMES = Set.of("uri", "url");

@Override
public CommandDescription generate(
List<CommandDescription> previousCommands,
List<Column> previousOutput,
QuerySchema schema,
QueryExecutor executor
) {
String inputExpression = pickUriInput(previousOutput);
if (inputExpression == null) {
return EMPTY_DESCRIPTION; // no string column or literal to use, skip
}
String prefixRaw = EsqlQueryGenerator.randomIdentifier();
String prefixForCmd = EsqlQueryGenerator.needsQuoting(prefixRaw) ? EsqlQueryGenerator.quote(prefixRaw) : prefixRaw;
String cmdString = " | uri_parts " + prefixForCmd + " = " + inputExpression;
return new CommandDescription(URI_PARTS, this, cmdString, Map.of(PREFIX, prefixRaw));
}

/**
* Pick the input for URI_PARTS: either a literal valid URI (so we exercise the happy path)
* or a string field, preferring columns named "uri" or "url" when present.
*/
private static String pickUriInput(List<Column> previousOutput) {
if (randomBoolean()) {
return "\"" + randomFrom(LITERAL_URIS) + "\"";
}
return uriLikeFieldOrRandomString(previousOutput);
}

private static String uriLikeFieldOrRandomString(List<Column> previousOutput) {
List<Column> stringColumns = previousOutput.stream()
.filter(c -> "keyword".equals(c.type()) || "text".equals(c.type()))
.filter(EsqlQueryGenerator::fieldCanBeUsed)
.toList();
if (stringColumns.isEmpty()) {
return null;
}
for (Column c : stringColumns) {
String name = c.name();
if (URI_LIKE_FIELD_NAMES.contains(EsqlQueryGenerator.unquote(name))) {
return EsqlQueryGenerator.needsQuoting(name) ? EsqlQueryGenerator.quote(name) : name;
}
}
Column chosen = randomFrom(stringColumns);
String name = chosen.name();
return EsqlQueryGenerator.needsQuoting(name) ? EsqlQueryGenerator.quote(name) : name;
}

@Override
public ValidationResult validateOutput(
List<CommandDescription> previousCommands,
CommandDescription commandDescription,
List<Column> previousColumns,
List<List<Object>> previousOutput,
List<Column> columns,
List<List<Object>> output
) {
if (commandDescription == EMPTY_DESCRIPTION) {
return VALIDATION_OK;
}

String prefix = (String) commandDescription.context().get(PREFIX);
if (prefix == null) {
return new ValidationResult(false, "Missing prefix in command context");
}

int expectedUriPartsColumns = URI_PARTS_OUTPUT_FIELDS.size();
int expectedTotal = previousColumns.size() + expectedUriPartsColumns;
if (columns.size() != expectedTotal) {
return new ValidationResult(
false,
"Expecting ["
+ expectedTotal
+ "] columns ("
+ previousColumns.size()
+ " previous + "
+ expectedUriPartsColumns
+ " URI_PARTS), got ["
+ columns.size()
+ "]"
);
}

var it = columns.iterator();
int pos = 0;

// Previous columns must appear first, in order, with the same name and type
for (Column prev : previousColumns) {
if (it.hasNext() == false) {
return new ValidationResult(false, "Missing previous column [" + prev.name() + "] in output");
}
Column actual = it.next();
pos++;
if (actual.name().equals(prev.name()) == false) {
return new ValidationResult(
false,
"At position " + pos + ": expected column [" + prev.name() + "], got [" + actual.name() + "]"
);
}
if (actual.type().equals(prev.type()) == false) {
return new ValidationResult(
false,
"Column [" + prev.name() + "] type changed from [" + prev.type() + "] to [" + actual.type() + "]"
);
}
}

// URI_PARTS columns must follow, in order, with the correct name and type
for (Map.Entry<String, String> e : URI_PARTS_OUTPUT_FIELDS.entrySet()) {
if (it.hasNext() == false) {
return new ValidationResult(
false,
"Missing URI_PARTS column [" + prefix + "." + e.getKey() + "] (expected type [" + e.getValue() + "])"
);
}
Column actual = it.next();
pos++;
String expectedName = prefix + "." + e.getKey();
String expectedType = e.getValue();
if (actual.name().equals(expectedName) == false) {
return new ValidationResult(
false,
"At position " + pos + ": expected URI_PARTS column [" + expectedName + "], got [" + actual.name() + "]"
);
}
if (actual.type().equals(expectedType) == false) {
return new ValidationResult(
false,
"URI_PARTS column [" + expectedName + "] expected type [" + expectedType + "], got [" + actual.type() + "]"
);
}
}

return VALIDATION_OK;
}
}