Skip to content

Commit 96fd1a2

Browse files
committed
ESQL: URL encoding changes
- Manually perform percent-encoding directly on the BreakingBytesRefBuilder scratch area, and only if the input was gonna change after encoding. - Use Apache's PercentEncode as the ground truth during unit testing. - Add test cases with fixed strings.
1 parent 9332d29 commit 96fd1a2

File tree

8 files changed

+286
-130
lines changed

8 files changed

+286
-130
lines changed

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/util/UrlCodecUtils.java

Lines changed: 0 additions & 92 deletions
This file was deleted.

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2609,10 +2609,10 @@ Georgi | georgi
26092609
url_encode mixed input tests
26102610
required_capability: url_encode
26112611

2612-
ROW u = ["hello elastic!", "a+b-c%d", "", "!#$&'()*+,/:;=?@[]"] | EVAL u = URL_ENCODE(u);
2612+
ROW u = ["hello elastic!", "a+b-c%d", "", ".-_~", "!#$&'()*+,/:;=?@[]"] | EVAL u = URL_ENCODE(u);
26132613

26142614
u:keyword
2615-
["hello+elastic%21", "a%2Bb-c%25d", "", "%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"]
2615+
["hello+elastic%21", "a%2Bb-c%25d", "", ".-_~", "%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"]
26162616
;
26172617

26182618
url_decode sample for docs
@@ -2718,12 +2718,13 @@ url_encode_component special input tests
27182718
required_capability: url_encode_component
27192719
required_capability: url_decode
27202720

2721-
ROW a = "+!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", b = "❗🐶🐱"
2721+
ROW a = "+!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", b = ".-_~", c = "❗🐶🐱"
27222722
| EVAL a = URL_ENCODE_COMPONENT(a)
2723-
| EVAL b = URL_DECODE(URL_ENCODE_COMPONENT(b));
2723+
| EVAL b = URL_ENCODE_COMPONENT(b)
2724+
| EVAL c = URL_DECODE(URL_ENCODE_COMPONENT(c));
27242725

2725-
a:keyword | b:keyword
2726-
"%2B%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~" | ❗🐶🐱
2726+
a:keyword | b:keyword | c:keyword
2727+
"%2B%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~" | ".-_~" |❗🐶🐱
27272728
;
27282729

27292730
url_encode_component tests with table reads

x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/UrlEncodeComponentEvaluator.java

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/UrlEncodeEvaluator.java

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/UrlEncode.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,25 @@
1111
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.compute.ann.ConvertEvaluator;
14+
import org.elasticsearch.compute.ann.Fixed;
15+
import org.elasticsearch.compute.operator.BreakingBytesRefBuilder;
1416
import org.elasticsearch.compute.operator.EvalOperator;
1517
import org.elasticsearch.xpack.esql.core.expression.Expression;
1618
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
1719
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1820
import org.elasticsearch.xpack.esql.core.tree.Source;
19-
import org.elasticsearch.xpack.esql.core.util.UrlCodecUtils;
2021
import org.elasticsearch.xpack.esql.expression.function.Example;
2122
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo;
2223
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle;
2324
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
2425
import org.elasticsearch.xpack.esql.expression.function.Param;
2526
import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction;
27+
import org.elasticsearch.xpack.esql.expression.function.scalar.util.UrlCodecUtils;
2628

2729
import java.io.IOException;
2830
import java.util.List;
2931

32+
import static org.elasticsearch.compute.ann.Fixed.Scope.THREAD_LOCAL;
3033
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString;
3134

3235
public final class UrlEncode extends UnaryScalarFunction {
@@ -81,15 +84,16 @@ protected TypeResolution resolveType() {
8184

8285
@Override
8386
public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
84-
return new UrlEncodeEvaluator.Factory(source(), toEvaluator.apply(field()));
87+
return new UrlEncodeEvaluator.Factory(
88+
source(),
89+
toEvaluator.apply(field()),
90+
context -> new BreakingBytesRefBuilder(context.breaker(), "url_encode")
91+
);
8592
}
8693

8794
@ConvertEvaluator()
88-
static BytesRef process(final BytesRef val) {
89-
byte[] input = new byte[val.length];
90-
System.arraycopy(val.bytes, val.offset, input, 0, val.length);
91-
byte[] bytes = UrlCodecUtils.encodeUrl(input);
92-
return new BytesRef(bytes);
95+
static BytesRef process(final BytesRef val, @Fixed(includeInToString = false, scope = THREAD_LOCAL) BreakingBytesRefBuilder scratch) {
96+
return UrlCodecUtils.urlEncode(val, scratch, true);
9397
}
9498

9599
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/UrlEncodeComponent.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,25 @@
1111
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.compute.ann.ConvertEvaluator;
14+
import org.elasticsearch.compute.ann.Fixed;
15+
import org.elasticsearch.compute.operator.BreakingBytesRefBuilder;
1416
import org.elasticsearch.compute.operator.EvalOperator;
1517
import org.elasticsearch.xpack.esql.core.expression.Expression;
1618
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
1719
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1820
import org.elasticsearch.xpack.esql.core.tree.Source;
19-
import org.elasticsearch.xpack.esql.core.util.UrlCodecUtils;
2021
import org.elasticsearch.xpack.esql.expression.function.Example;
2122
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo;
2223
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle;
2324
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
2425
import org.elasticsearch.xpack.esql.expression.function.Param;
2526
import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction;
27+
import org.elasticsearch.xpack.esql.expression.function.scalar.util.UrlCodecUtils;
2628

2729
import java.io.IOException;
2830
import java.util.List;
2931

32+
import static org.elasticsearch.compute.ann.Fixed.Scope.THREAD_LOCAL;
3033
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString;
3134

3235
public class UrlEncodeComponent extends UnaryScalarFunction {
@@ -81,15 +84,16 @@ protected TypeResolution resolveType() {
8184

8285
@Override
8386
public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
84-
return new UrlEncodeComponentEvaluator.Factory(source(), toEvaluator.apply(field()));
87+
return new UrlEncodeComponentEvaluator.Factory(
88+
source(),
89+
toEvaluator.apply(field()),
90+
context -> new BreakingBytesRefBuilder(context.breaker(), "url_encode_component")
91+
);
8592
}
8693

8794
@ConvertEvaluator()
88-
static BytesRef process(final BytesRef val) {
89-
byte[] input = new byte[val.length];
90-
System.arraycopy(val.bytes, val.offset, input, 0, val.length);
91-
byte[] bytes = UrlCodecUtils.encodeUrlComponent(input);
92-
return new BytesRef(bytes);
95+
static BytesRef process(final BytesRef val, @Fixed(includeInToString = false, scope = THREAD_LOCAL) BreakingBytesRefBuilder scratch) {
96+
return UrlCodecUtils.urlEncode(val, scratch, false);
9397
}
9498

9599
}

0 commit comments

Comments
 (0)