forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds package javadoc for ESLQ's `function.scalar` package with instructions on how to write a function.
- Loading branch information
Showing
1 changed file
with
154 additions
and
0 deletions.
There are no files selected for viewing
154 changes: 154 additions & 0 deletions
154
...l/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
/** | ||
* Functions that take a row of data and produce a row of data without holding | ||
* any state between rows. This includes both the {@link org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction} | ||
* subclass to link into the QL infrastucture and the {@link org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator} | ||
* implementation to run the actual function. | ||
* | ||
* <h2>Guide to adding new function</h2> | ||
* <p> | ||
* Adding functions is <strong>fairly</strong> easy and should be fun! | ||
* This is a step by step list of how to do it. | ||
* </p> | ||
* <ol> | ||
* <li>Fork the <a href="github.com/elastic/elasticsearch">Elasticsearch repo</a>.</li> | ||
* <li>Clone your fork locally.</li> | ||
* <li>Add Elastic's remote, it should look a little like: | ||
* {@code<pre> | ||
* [remote "elastic"] | ||
* url = git@github.com:elastic/elasticsearch.git | ||
* fetch = +refs/heads/*:refs/remotes/elastic/* | ||
* [remote "nik9000"] | ||
* url = git@github.com:nik9000/elasticsearch.git | ||
* fetch = +refs/heads/*:refs/remotes/nik9000/* | ||
* </pre>} | ||
* </li> | ||
* <li> | ||
* Feel free to use {@code git} as a scratch pad. We're going to squash all commits | ||
* before merging and will only keep the PR subject line and description in the | ||
* commit message. | ||
* </li> | ||
* <li> | ||
* Open Elasticsearch in IntelliJ. | ||
* </li> | ||
* <li> | ||
* Open {@code x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java} | ||
* and run it. IntelliJ will take a few minutes to compile everything but the test itself | ||
* should take only a few seconds. This is a fast path to running ESQL's integration tests. | ||
* </li> | ||
* <li> | ||
* Pick one of the csv-spec files in {@code x-pack/plugin/esql/qa/testFixtures/src/main/resources/} | ||
* and add a test for the function you want to write. These files are roughly themed but there | ||
* isn't a strong guiding principle in the theme. | ||
* </li> | ||
* <li> | ||
* Rerun the {@code CsvTests} and watch your new test fail. Yay, TDD doing it's job. | ||
* </li> | ||
* <li> | ||
* Find a function in this package similar to the one you are working on and copy it to build | ||
* yours. There's come ceremony required in each function class to make it constant foldable | ||
* and return the right types. Take a stab at these, but don't worry too much about getting | ||
* it right. | ||
* </li> | ||
* <li> | ||
* There are also methods annotated with {@link org.elasticsearch.compute.ann.Evaluator} | ||
* that contain the actual inner implementation of the function. Modify those to look right | ||
* and click {@code Build->Recompile 'FunctionName.java'} in IntelliJ. This should generate | ||
* an {@link org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator} implementation | ||
* calling the method annotated with {@link org.elasticsearch.compute.ann.Evaluator}. | ||
* <li> | ||
* Once your evaluator is generated you can implement {@link org.elasticsearch.xpack.esql.planner.Mappable#toEvaluator}, | ||
* having it return the generated evaluator. | ||
* </li> | ||
* <li> | ||
* Add your function to {@link org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry}. | ||
* This links it into the language and {@code SHOW FUNCTIONS}. Also add your function to | ||
* {@link org.elasticsearch.xpack.esql.io.stream.PlanNamedTypes}. This makes your function | ||
* serializable over the wire. Mostly you can copy existing implementations for both. | ||
* </li> | ||
* <li> | ||
* Rerun the {@code CsvTests}. They should find your function and maybe even pass. Add a | ||
* few more tests in the csv-spec tests. They run quickly so it isn't a big deal having | ||
* half a dozen of them per function. | ||
* </li> | ||
* <li> | ||
* Now it's time to make a unit test! The infrastructure for these is under some flux at | ||
* the moment, but it's good to extend from {@code AbstractScalarFunctionTestCase}. All of | ||
* these tests are parameterized and expect to spend some time finding good parameters. | ||
* </li> | ||
* <li> | ||
* Once you are happy with the tests run the auto formatter: | ||
* {@code<pre>./gradlew -p x-pack/plugin/esql/ spotlessApply</pre>} | ||
* </li> | ||
* <li> | ||
* Now you can run all of the ESQL tests liks CI: | ||
* {@code<pre>./gradlew -p x-pack/plugin/esql/ check</pre>} | ||
* </li> | ||
* <li> | ||
* Now it's time to write some docs! Open {@code docs/reference/esql/esql-functions.asciidoc} | ||
* and add your function in alphabetical order to the list at the top and then add it to | ||
* the includes below. | ||
* </li> | ||
* <li> | ||
* Now go make a file to include. You can start by copying one of it's neighbors. | ||
* </li> | ||
* <li> | ||
* It's important that any examples you add to the docs be included from the csv-spec file. | ||
* That looks like: | ||
* {@code<pre> | ||
* [source.merge.styled,esql] | ||
* ---- | ||
* include::{esql-specs}/math.csv-spec[tag=mv_min] | ||
* ---- | ||
* [%header.monospaced.styled,format=dsv,separator=|] | ||
* |=== | ||
* include::{esql-specs}/math.csv-spec[tag=mv_min-result] | ||
* |=== | ||
* </pre>} | ||
* This includes the bit of the csv-spec file fenced by {@code // tag::mv_min[]}. You'll | ||
* want a fence descriptive for your function. Consider the non-includes lines to be | ||
* asciidoc ceremony to make the result look right in the rendered docs. | ||
* </li> | ||
* <li> | ||
* Build the docs by cloning the <a href="https://github.com/elastic/docs">docs repo</a> | ||
* and running: | ||
* {@code<pre> | ||
* ../docs/build_docs --doc docs/reference/index.asciidoc --resource x-pack/docs/ --open --chunk 1 | ||
* </pre>} | ||
* from the elasticsearch directory. The first time you run the docs build it does a bunch | ||
* of things with docker to get itself ready. Hopefully you can sit back and watch the show. | ||
* It won't need to do it a second time unless some poor soul updates the Dockerfile in the | ||
* docs repo. | ||
* </li> | ||
* <li> | ||
* When it finishes building it'll open a browser window. Go to the | ||
* <a href="http://localhost:8000/guide/esql-functions.html">functions page</a> to see your | ||
* function in the list and follow it's link to get to the page you built. Make sure it | ||
* looks ok. | ||
* </li> | ||
* <li> | ||
* Open the PR. The subject and description of the PR are important because those'll turn | ||
* into the commit message we see in the commit history. Good PR descriptions make me very | ||
* happy. But functions don't need an essay. | ||
* </li> | ||
* <li> | ||
* Add the {@code >enhancement} and {@code :Query Languages/ES|QL} tags if you are able. | ||
* Request a review if you can, probably from one of the folks that github proposes to you. | ||
* </li> | ||
* <li> | ||
* CI might fail for random looking reasons. The first thing you should do is merge {@code main} | ||
* into your PR branch. That's usually just: | ||
* {@code<pre> | ||
* git checkout main && git pull elastic main && git checkout mybranch && git merge main | ||
* </pre>} | ||
* Don't worry about the commit message. It'll get squashed away in the merge. | ||
* </li> | ||
* </ol> | ||
*/ | ||
package org.elasticsearch.xpack.esql.expression.function.scalar; |