From ecd700e537cef042a7e6f907f39581750140de8a Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Wed, 27 Aug 2025 14:50:25 -0400 Subject: [PATCH 1/2] ESQL: Patch kibana signature for BUCKET Our signature handling code considers the second and third arguments of BUCKET to be optional - the railroad diagram and function registry consider those arguments optional. But in another sense, these function arguments aren't optional - they are required IF you are invoking the certain types. This patches the generated kibana signature to it'll look and feel right. --- .../kibana/definition/functions/bucket.json | 180 +++++++++--------- .../function/EsqlFunctionRegistry.java | 4 + .../expression/function/DocsV3Support.java | 25 ++- .../function/grouping/BucketTests.java | 12 ++ 4 files changed, 130 insertions(+), 91 deletions(-) diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/bucket.json b/docs/reference/query-languages/esql/kibana/definition/functions/bucket.json index 81f2d695d4698..684707f76fddc 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/bucket.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/bucket.json @@ -39,13 +39,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -69,13 +69,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -99,13 +99,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -129,13 +129,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -159,13 +159,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -189,13 +189,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -219,13 +219,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -249,13 +249,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -279,13 +279,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -345,13 +345,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -375,13 +375,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -405,13 +405,13 @@ { "name" : "from", "type" : "date", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -435,13 +435,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -465,13 +465,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -495,13 +495,13 @@ { "name" : "from", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -525,13 +525,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "date", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -555,13 +555,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "keyword", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -585,13 +585,13 @@ { "name" : "from", "type" : "text", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "text", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -669,13 +669,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -699,13 +699,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -729,13 +729,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -759,13 +759,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -789,13 +789,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -819,13 +819,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -849,13 +849,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -879,13 +879,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -909,13 +909,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -993,13 +993,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1023,13 +1023,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1053,13 +1053,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1083,13 +1083,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1113,13 +1113,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1143,13 +1143,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1173,13 +1173,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1203,13 +1203,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1233,13 +1233,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1317,13 +1317,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1347,13 +1347,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1377,13 +1377,13 @@ { "name" : "from", "type" : "double", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1407,13 +1407,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1437,13 +1437,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1467,13 +1467,13 @@ { "name" : "from", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1497,13 +1497,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "double", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1527,13 +1527,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "integer", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], @@ -1557,13 +1557,13 @@ { "name" : "from", "type" : "long", - "optional" : true, + "optional" : false, "description" : "Start of the range. Can be a number, a date or a date expressed as a string." }, { "name" : "to", "type" : "long", - "optional" : true, + "optional" : false, "description" : "End of the range. Can be a number, a date or a date expressed as a string." } ], diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index b47ca9fa8d4d8..2912fbfdbbadc 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -580,6 +580,10 @@ public boolean optional() { return optional; } + public boolean variadic() { + return variadic; + } + public DataType targetDataType() { return targetDataType; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java index 5e3d3b2bb032b..224cba34c8d8c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java @@ -380,6 +380,7 @@ public License.OperationMode invoke(List fieldTypes) throws Exception protected final Supplier> signatures; protected final Callbacks callbacks; private final LicenseRequirementChecker licenseChecker; + private final KibanaSignaturePatcher kibanaSignaturePatcher; protected DocsV3Support( String category, @@ -405,6 +406,7 @@ private DocsV3Support( this.signatures = signatures; this.callbacks = callbacks; this.licenseChecker = new LicenseRequirementChecker(testClass); + this.kibanaSignaturePatcher = new KibanaSignaturePatcher(testClass); } String replaceLinks(String text) { @@ -1321,7 +1323,7 @@ void renderKibanaFunctionDefinition( builder.startObject(); builder.startArray("params"); for (int i = 0; i < sig.argTypes().size(); i++) { - EsqlFunctionRegistry.ArgSignature arg = args.get(i); + EsqlFunctionRegistry.ArgSignature arg = kibanaSignaturePatcher.invoke(args.get(i)); builder.startObject(); builder.field("name", arg.name()); if (arg.mapArg()) { @@ -1536,4 +1538,25 @@ public static Callbacks callbacksFromSystemProperty() { default -> throw new IllegalArgumentException("unsupported value for generateDocs [" + prop + "]"); }; } + + public static class KibanaSignaturePatcher { + private final Method staticMethod; + + public KibanaSignaturePatcher(Class testClass) { + Method staticMethod; + try { + staticMethod = testClass.getMethod("patchKibanaSignature", EsqlFunctionRegistry.ArgSignature.class); + } catch (NoSuchMethodException e) { + staticMethod = null; + } + this.staticMethod = staticMethod; + } + + public EsqlFunctionRegistry.ArgSignature invoke(EsqlFunctionRegistry.ArgSignature fieldTypes) throws Exception { + if (staticMethod == null) { + return fieldTypes; + } + return (EsqlFunctionRegistry.ArgSignature) staticMethod.invoke(null, fieldTypes); + } + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java index f01b06c23e8a8..ad76a04d0056b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; +import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; import org.hamcrest.Matcher; import org.hamcrest.Matchers; @@ -325,4 +326,15 @@ protected Expression build(Source source, List args) { } return new Bucket(source, args.get(0), args.get(1), from, to); } + + public static EsqlFunctionRegistry.ArgSignature patchKibanaSignature(EsqlFunctionRegistry.ArgSignature arg) { + return new EsqlFunctionRegistry.ArgSignature( + arg.name(), + arg.type(), + arg.description(), + false, + arg.variadic(), + arg.targetDataType() + ); + } } From c782e1a68339f91b10669ce5bf5ab4bf410d2767 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Wed, 27 Aug 2025 15:40:54 -0400 Subject: [PATCH 2/2] Explain --- .../function/grouping/BucketTests.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java index ad76a04d0056b..4d3c1cc2a7cdd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/grouping/BucketTests.java @@ -327,6 +327,23 @@ protected Expression build(Source source, List args) { return new Bucket(source, args.get(0), args.get(1), from, to); } + /** + * In Elasticsearch, we think of these parameters are optional because you don't + * have to supply them. But you have to supply them in some cases. It depends on + * the signatures. And when we're rendering the signatures for kibana it's more + * correct to say that all parameters are required. They'll render like + *
{@code
+     * | field | buckets | from | to | result |
+     * | --- | --- | --- | --- | --- |
+     * | date | date_period | | | date |
+     * | date | time_duration | | | date |
+     * | date | integer | date | date | date |
+     * | double | double | | | double |
+     * | double | integer | double | double | double |
+     * ...
+     * }
+ * And all of those listed versions *are* required. + */ public static EsqlFunctionRegistry.ArgSignature patchKibanaSignature(EsqlFunctionRegistry.ArgSignature arg) { return new EsqlFunctionRegistry.ArgSignature( arg.name(),