瀏覽代碼

Hash functions (#118938) (#119769)

This change adds md5, sha1 and sha256 hash functions.
Ievgen Degtiarenko 9 月之前
父節點
當前提交
b398448848
共有 50 個文件被更改,包括 1003 次插入9 次删除
  1. 5 0
      docs/changelog/118938.yaml
  2. 5 0
      docs/reference/esql/functions/description/md5.asciidoc
  3. 5 0
      docs/reference/esql/functions/description/sha1.asciidoc
  4. 5 0
      docs/reference/esql/functions/description/sha256.asciidoc
  5. 13 0
      docs/reference/esql/functions/examples/hash.asciidoc
  6. 13 0
      docs/reference/esql/functions/examples/md5.asciidoc
  7. 13 0
      docs/reference/esql/functions/examples/sha1.asciidoc
  8. 13 0
      docs/reference/esql/functions/examples/sha256.asciidoc
  9. 3 0
      docs/reference/esql/functions/kibana/definition/hash.json
  10. 37 0
      docs/reference/esql/functions/kibana/definition/md5.json
  11. 37 0
      docs/reference/esql/functions/kibana/definition/sha1.json
  12. 37 0
      docs/reference/esql/functions/kibana/definition/sha256.json
  13. 6 0
      docs/reference/esql/functions/kibana/docs/hash.md
  14. 13 0
      docs/reference/esql/functions/kibana/docs/md5.md
  15. 13 0
      docs/reference/esql/functions/kibana/docs/sha1.md
  16. 13 0
      docs/reference/esql/functions/kibana/docs/sha256.md
  17. 1 0
      docs/reference/esql/functions/layout/hash.asciidoc
  18. 15 0
      docs/reference/esql/functions/layout/md5.asciidoc
  19. 15 0
      docs/reference/esql/functions/layout/sha1.asciidoc
  20. 15 0
      docs/reference/esql/functions/layout/sha256.asciidoc
  21. 6 0
      docs/reference/esql/functions/parameters/md5.asciidoc
  22. 6 0
      docs/reference/esql/functions/parameters/sha1.asciidoc
  23. 6 0
      docs/reference/esql/functions/parameters/sha256.asciidoc
  24. 1 0
      docs/reference/esql/functions/signature/md5.svg
  25. 1 0
      docs/reference/esql/functions/signature/sha1.svg
  26. 1 0
      docs/reference/esql/functions/signature/sha256.svg
  27. 6 0
      docs/reference/esql/functions/string-functions.asciidoc
  28. 10 0
      docs/reference/esql/functions/types/md5.asciidoc
  29. 10 0
      docs/reference/esql/functions/types/sha1.asciidoc
  30. 10 0
      docs/reference/esql/functions/types/sha256.asciidoc
  31. 70 3
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/hash.csv-spec
  32. 4 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
  33. 6 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java
  34. 6 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ScalarFunctionWritables.java
  35. 70 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/AbstractHashFunction.java
  36. 13 3
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Hash.java
  37. 61 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5.java
  38. 60 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1.java
  39. 60 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256.java
  40. 11 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/HashTests.java
  41. 38 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5ErrorTests.java
  42. 25 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5SerializationTests.java
  43. 39 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5Tests.java
  44. 38 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1ErrorTests.java
  45. 25 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1SerializationTests.java
  46. 39 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1Tests.java
  47. 38 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256ErrorTests.java
  48. 25 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256SerializationTests.java
  49. 39 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256Tests.java
  50. 2 2
      x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml

+ 5 - 0
docs/changelog/118938.yaml

@@ -0,0 +1,5 @@
+pr: 118938
+summary: Hash functions
+area: ES|QL
+type: enhancement
+issues: []

+ 5 - 0
docs/reference/esql/functions/description/md5.asciidoc

@@ -0,0 +1,5 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Description*
+
+Computes the MD5 hash of the input.

+ 5 - 0
docs/reference/esql/functions/description/sha1.asciidoc

@@ -0,0 +1,5 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Description*
+
+Computes the SHA1 hash of the input.

+ 5 - 0
docs/reference/esql/functions/description/sha256.asciidoc

@@ -0,0 +1,5 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Description*
+
+Computes the SHA256 hash of the input.

+ 13 - 0
docs/reference/esql/functions/examples/hash.asciidoc

@@ -0,0 +1,13 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/hash.csv-spec[tag=hash]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/hash.csv-spec[tag=hash-result]
+|===
+

+ 13 - 0
docs/reference/esql/functions/examples/md5.asciidoc

@@ -0,0 +1,13 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/hash.csv-spec[tag=md5]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/hash.csv-spec[tag=md5-result]
+|===
+

+ 13 - 0
docs/reference/esql/functions/examples/sha1.asciidoc

@@ -0,0 +1,13 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/hash.csv-spec[tag=sha1]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/hash.csv-spec[tag=sha1-result]
+|===
+

+ 13 - 0
docs/reference/esql/functions/examples/sha256.asciidoc

@@ -0,0 +1,13 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/hash.csv-spec[tag=sha256]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/hash.csv-spec[tag=sha256-result]
+|===
+

+ 3 - 0
docs/reference/esql/functions/kibana/definition/hash.json

@@ -77,6 +77,9 @@
       "returnType" : "keyword"
     }
   ],
+  "examples" : [
+    "FROM sample_data \n| WHERE message != \"Connection error\"\n| EVAL md5 = hash(\"md5\", message), sha256 = hash(\"sha256\", message) \n| KEEP message, md5, sha256;"
+  ],
   "preview" : false,
   "snapshot_only" : false
 }

+ 37 - 0
docs/reference/esql/functions/kibana/definition/md5.json

@@ -0,0 +1,37 @@
+{
+  "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.",
+  "type" : "eval",
+  "name" : "md5",
+  "description" : "Computes the MD5 hash of the input.",
+  "signatures" : [
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "keyword",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    },
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "text",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    }
+  ],
+  "examples" : [
+    "FROM sample_data \n| WHERE message != \"Connection error\"\n| EVAL md5 = md5(message)\n| KEEP message, md5;"
+  ],
+  "preview" : false,
+  "snapshot_only" : false
+}

+ 37 - 0
docs/reference/esql/functions/kibana/definition/sha1.json

@@ -0,0 +1,37 @@
+{
+  "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.",
+  "type" : "eval",
+  "name" : "sha1",
+  "description" : "Computes the SHA1 hash of the input.",
+  "signatures" : [
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "keyword",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    },
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "text",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    }
+  ],
+  "examples" : [
+    "FROM sample_data \n| WHERE message != \"Connection error\"\n| EVAL sha1 = sha1(message)\n| KEEP message, sha1;"
+  ],
+  "preview" : false,
+  "snapshot_only" : false
+}

+ 37 - 0
docs/reference/esql/functions/kibana/definition/sha256.json

@@ -0,0 +1,37 @@
+{
+  "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.",
+  "type" : "eval",
+  "name" : "sha256",
+  "description" : "Computes the SHA256 hash of the input.",
+  "signatures" : [
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "keyword",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    },
+    {
+      "params" : [
+        {
+          "name" : "input",
+          "type" : "text",
+          "optional" : false,
+          "description" : "Input to hash."
+        }
+      ],
+      "variadic" : false,
+      "returnType" : "keyword"
+    }
+  ],
+  "examples" : [
+    "FROM sample_data \n| WHERE message != \"Connection error\"\n| EVAL sha256 = sha256(message)\n| KEEP message, sha256;"
+  ],
+  "preview" : false,
+  "snapshot_only" : false
+}

+ 6 - 0
docs/reference/esql/functions/kibana/docs/hash.md

@@ -5,3 +5,9 @@ This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../READ
 ### HASH
 Computes the hash of the input using various algorithms such as MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512.
 
+```
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL md5 = hash("md5", message), sha256 = hash("sha256", message) 
+| KEEP message, md5, sha256;
+```

+ 13 - 0
docs/reference/esql/functions/kibana/docs/md5.md

@@ -0,0 +1,13 @@
+<!--
+This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+-->
+
+### MD5
+Computes the MD5 hash of the input.
+
+```
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL md5 = md5(message)
+| KEEP message, md5;
+```

+ 13 - 0
docs/reference/esql/functions/kibana/docs/sha1.md

@@ -0,0 +1,13 @@
+<!--
+This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+-->
+
+### SHA1
+Computes the SHA1 hash of the input.
+
+```
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL sha1 = sha1(message)
+| KEEP message, sha1;
+```

+ 13 - 0
docs/reference/esql/functions/kibana/docs/sha256.md

@@ -0,0 +1,13 @@
+<!--
+This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+-->
+
+### SHA256
+Computes the SHA256 hash of the input.
+
+```
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL sha256 = sha256(message)
+| KEEP message, sha256;
+```

+ 1 - 0
docs/reference/esql/functions/layout/hash.asciidoc

@@ -12,3 +12,4 @@ image::esql/functions/signature/hash.svg[Embedded,opts=inline]
 include::../parameters/hash.asciidoc[]
 include::../description/hash.asciidoc[]
 include::../types/hash.asciidoc[]
+include::../examples/hash.asciidoc[]

+ 15 - 0
docs/reference/esql/functions/layout/md5.asciidoc

@@ -0,0 +1,15 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+[discrete]
+[[esql-md5]]
+=== `MD5`
+
+*Syntax*
+
+[.text-center]
+image::esql/functions/signature/md5.svg[Embedded,opts=inline]
+
+include::../parameters/md5.asciidoc[]
+include::../description/md5.asciidoc[]
+include::../types/md5.asciidoc[]
+include::../examples/md5.asciidoc[]

+ 15 - 0
docs/reference/esql/functions/layout/sha1.asciidoc

@@ -0,0 +1,15 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+[discrete]
+[[esql-sha1]]
+=== `SHA1`
+
+*Syntax*
+
+[.text-center]
+image::esql/functions/signature/sha1.svg[Embedded,opts=inline]
+
+include::../parameters/sha1.asciidoc[]
+include::../description/sha1.asciidoc[]
+include::../types/sha1.asciidoc[]
+include::../examples/sha1.asciidoc[]

+ 15 - 0
docs/reference/esql/functions/layout/sha256.asciidoc

@@ -0,0 +1,15 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+[discrete]
+[[esql-sha256]]
+=== `SHA256`
+
+*Syntax*
+
+[.text-center]
+image::esql/functions/signature/sha256.svg[Embedded,opts=inline]
+
+include::../parameters/sha256.asciidoc[]
+include::../description/sha256.asciidoc[]
+include::../types/sha256.asciidoc[]
+include::../examples/sha256.asciidoc[]

+ 6 - 0
docs/reference/esql/functions/parameters/md5.asciidoc

@@ -0,0 +1,6 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Parameters*
+
+`input`::
+Input to hash.

+ 6 - 0
docs/reference/esql/functions/parameters/sha1.asciidoc

@@ -0,0 +1,6 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Parameters*
+
+`input`::
+Input to hash.

+ 6 - 0
docs/reference/esql/functions/parameters/sha256.asciidoc

@@ -0,0 +1,6 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Parameters*
+
+`input`::
+Input to hash.

+ 1 - 0
docs/reference/esql/functions/signature/md5.svg

@@ -0,0 +1 @@
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="240" height="46" viewbox="0 0 240 46"><defs><style type="text/css">#guide .c{fill:none;stroke:#222222;}#guide .k{fill:#000000;font-family:Roboto Mono,Sans-serif;font-size:20px;}#guide .s{fill:#e4f4ff;stroke:#222222;}#guide .syn{fill:#8D8D8D;font-family:Roboto Mono,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 31h5m56 0h10m32 0h10m80 0h10m32 0h5"/><rect class="s" x="5" y="5" width="56" height="36"/><text class="k" x="15" y="31">MD5</text><rect class="s" x="71" y="5" width="32" height="36" rx="7"/><text class="syn" x="81" y="31">(</text><rect class="s" x="113" y="5" width="80" height="36" rx="7"/><text class="k" x="123" y="31">input</text><rect class="s" x="203" y="5" width="32" height="36" rx="7"/><text class="syn" x="213" y="31">)</text></svg>

+ 1 - 0
docs/reference/esql/functions/signature/sha1.svg

@@ -0,0 +1 @@
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="252" height="46" viewbox="0 0 252 46"><defs><style type="text/css">#guide .c{fill:none;stroke:#222222;}#guide .k{fill:#000000;font-family:Roboto Mono,Sans-serif;font-size:20px;}#guide .s{fill:#e4f4ff;stroke:#222222;}#guide .syn{fill:#8D8D8D;font-family:Roboto Mono,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 31h5m68 0h10m32 0h10m80 0h10m32 0h5"/><rect class="s" x="5" y="5" width="68" height="36"/><text class="k" x="15" y="31">SHA1</text><rect class="s" x="83" y="5" width="32" height="36" rx="7"/><text class="syn" x="93" y="31">(</text><rect class="s" x="125" y="5" width="80" height="36" rx="7"/><text class="k" x="135" y="31">input</text><rect class="s" x="215" y="5" width="32" height="36" rx="7"/><text class="syn" x="225" y="31">)</text></svg>

+ 1 - 0
docs/reference/esql/functions/signature/sha256.svg

@@ -0,0 +1 @@
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="276" height="46" viewbox="0 0 276 46"><defs><style type="text/css">#guide .c{fill:none;stroke:#222222;}#guide .k{fill:#000000;font-family:Roboto Mono,Sans-serif;font-size:20px;}#guide .s{fill:#e4f4ff;stroke:#222222;}#guide .syn{fill:#8D8D8D;font-family:Roboto Mono,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 31h5m92 0h10m32 0h10m80 0h10m32 0h5"/><rect class="s" x="5" y="5" width="92" height="36"/><text class="k" x="15" y="31">SHA256</text><rect class="s" x="107" y="5" width="32" height="36" rx="7"/><text class="syn" x="117" y="31">(</text><rect class="s" x="149" y="5" width="80" height="36" rx="7"/><text class="k" x="159" y="31">input</text><rect class="s" x="239" y="5" width="32" height="36" rx="7"/><text class="syn" x="249" y="31">)</text></svg>

+ 6 - 0
docs/reference/esql/functions/string-functions.asciidoc

@@ -18,11 +18,14 @@
 * <<esql-length>>
 * <<esql-locate>>
 * <<esql-ltrim>>
+* <<esql-md5>>
 * <<esql-repeat>>
 * <<esql-replace>>
 * <<esql-reverse>>
 * <<esql-right>>
 * <<esql-rtrim>>
+* <<esql-sha1>>
+* <<esql-sha256>>
 * <<esql-space>>
 * <<esql-split>>
 * <<esql-starts_with>>
@@ -43,11 +46,14 @@ include::layout/left.asciidoc[]
 include::layout/length.asciidoc[]
 include::layout/locate.asciidoc[]
 include::layout/ltrim.asciidoc[]
+include::layout/md5.asciidoc[]
 include::layout/repeat.asciidoc[]
 include::layout/replace.asciidoc[]
 include::layout/reverse.asciidoc[]
 include::layout/right.asciidoc[]
 include::layout/rtrim.asciidoc[]
+include::layout/sha1.asciidoc[]
+include::layout/sha256.asciidoc[]
 include::layout/space.asciidoc[]
 include::layout/split.asciidoc[]
 include::layout/starts_with.asciidoc[]

+ 10 - 0
docs/reference/esql/functions/types/md5.asciidoc

@@ -0,0 +1,10 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Supported types*
+
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+input | result
+keyword | keyword
+text | keyword
+|===

+ 10 - 0
docs/reference/esql/functions/types/sha1.asciidoc

@@ -0,0 +1,10 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Supported types*
+
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+input | result
+keyword | keyword
+text | keyword
+|===

+ 10 - 0
docs/reference/esql/functions/types/sha256.asciidoc

@@ -0,0 +1,10 @@
+// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+
+*Supported types*
+
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+input | result
+keyword | keyword
+text | keyword
+|===

+ 70 - 3
x-pack/plugin/esql/qa/testFixtures/src/main/resources/hash.csv-spec

@@ -1,18 +1,22 @@
 hash
 required_capability: hash_function
 
+// tag::hash[]
 FROM sample_data 
 | WHERE message != "Connection error"
 | EVAL md5 = hash("md5", message), sha256 = hash("sha256", message) 
 | KEEP message, md5, sha256;
+// end::hash[]
 ignoreOrder:true
 
+// tag::hash-result[]
 message:keyword       | md5:keyword                      | sha256:keyword
 Connected to 10.1.0.1 | abd7d1ce2bb636842a29246b3512dcae | 6d8372129ad78770f7185554dd39864749a62690216460752d6c075fa38ad85c
 Connected to 10.1.0.2 | 8f8f1cb60832d153f5b9ec6dc828b93f | b0db24720f15857091b3c99f4c4833586d0ea3229911b8777efb8d917cf27e9a
 Connected to 10.1.0.3 | 912b6dc13503165a15de43304bb77c78 | 75b0480188db8acc4d5cc666a51227eb2bc5b989cd8ca912609f33e0846eff57
 Disconnected          | ef70e46fd3bbc21e3e1f0b6815e750c0 | 04dfac3671b494ad53fcd152f7a14511bfb35747278aad8ce254a0d6e4ba4718
 ;
+// end::hash-result[]
 
 
 hashOfConvertedType
@@ -94,12 +98,75 @@ input:integer | md5:keyword                      | sha256:keyword
 
 hashWithStats
 required_capability: hash_function
+required_capability: hash_function_aliases_v1
 
 FROM sample_data 
 | EVAL md5="md5"
-| STATS count = count(*) by hash(md5, message)
+| STATS count = count(*) by hash(md5, message), md5(message), sha1(message), sha256(message)
 | WHERE count > 1;
 
-count:long | hash(md5, message):keyword
-3          | 2e92ae79ff32b37fee4368a594792183
+count:long | hash(md5, message):keyword        | md5(message):keyword             | sha1(message):keyword                    | sha256(message):keyword
+3          | 2e92ae79ff32b37fee4368a594792183  | 2e92ae79ff32b37fee4368a594792183 | 1dbb3521876a899f82d6b0ff10eb32a01e03aba8 | 8d137af9c64fba09bbb003aba93f0b029898fe19e7927cd696f4c3e2b69f538d
 ;
+
+
+md5Hash
+required_capability: hash_function_aliases_v1
+
+// tag::md5[]
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL md5 = md5(message)
+| KEEP message, md5;
+// end::md5[]
+ignoreOrder:true
+
+// tag::md5-result[]
+message:keyword       | md5:keyword
+Connected to 10.1.0.1 | abd7d1ce2bb636842a29246b3512dcae
+Connected to 10.1.0.2 | 8f8f1cb60832d153f5b9ec6dc828b93f
+Connected to 10.1.0.3 | 912b6dc13503165a15de43304bb77c78
+Disconnected          | ef70e46fd3bbc21e3e1f0b6815e750c0
+;
+// end::md5-result[]
+
+
+sha1Hash
+required_capability: hash_function_aliases_v1
+
+// tag::sha1[]
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL sha1 = sha1(message)
+| KEEP message, sha1;
+// end::sha1[]
+ignoreOrder:true
+
+// tag::sha1-result[]
+message:keyword       | sha1:keyword
+Connected to 10.1.0.1 | 42b85531a79088036a17759db7d2de292b92f57f
+Connected to 10.1.0.2 | d30db445da2e9237c9718d0c7e4fb7cbbe9c2cb4
+Connected to 10.1.0.3 | 2733848d943809f0b10cad3e980763e88afb9853
+Disconnected          | 771e05f27b99fd59f638f41a7a4e977b1d4691fe
+;
+// end::sha1-result[]
+
+sha256Hash
+required_capability: hash_function_aliases_v1
+
+// tag::sha256[]
+FROM sample_data 
+| WHERE message != "Connection error"
+| EVAL sha256 = sha256(message)
+| KEEP message, sha256;
+// end::sha256[]
+ignoreOrder:true
+
+// tag::sha256-result[]
+message:keyword       | sha256:keyword
+Connected to 10.1.0.1 | 6d8372129ad78770f7185554dd39864749a62690216460752d6c075fa38ad85c
+Connected to 10.1.0.2 | b0db24720f15857091b3c99f4c4833586d0ea3229911b8777efb8d917cf27e9a
+Connected to 10.1.0.3 | 75b0480188db8acc4d5cc666a51227eb2bc5b989cd8ca912609f33e0846eff57
+Disconnected          | 04dfac3671b494ad53fcd152f7a14511bfb35747278aad8ce254a0d6e4ba4718
+;
+// end::sha256-result[]

+ 4 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

@@ -451,6 +451,10 @@ public class EsqlCapabilities {
          * Hash function
          */
         HASH_FUNCTION,
+        /**
+         * Hash function aliases such as MD5
+         */
+        HASH_FUNCTION_ALIASES_V1,
 
         /**
          * Don't optimize CASE IS NOT NULL function by not requiring the fields to be not null as well.

+ 6 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java

@@ -134,11 +134,14 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.LTrim;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Left;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Length;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Locate;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Md5;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.RTrim;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Repeat;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Replace;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Reverse;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Right;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Sha1;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Sha256;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Space;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Split;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.StartsWith;
@@ -333,11 +336,14 @@ public class EsqlFunctionRegistry {
                 def(Left.class, Left::new, "left"),
                 def(Length.class, Length::new, "length"),
                 def(Locate.class, Locate::new, "locate"),
+                def(Md5.class, Md5::new, "md5"),
                 def(RTrim.class, RTrim::new, "rtrim"),
                 def(Repeat.class, Repeat::new, "repeat"),
                 def(Replace.class, Replace::new, "replace"),
                 def(Reverse.class, Reverse::new, "reverse"),
                 def(Right.class, Right::new, "right"),
+                def(Sha1.class, Sha1::new, "sha1"),
+                def(Sha256.class, Sha256::new, "sha256"),
                 def(Space.class, Space::new, "space"),
                 def(StartsWith.class, StartsWith::new, "starts_with"),
                 def(Substring.class, Substring::new, "substring"),

+ 6 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ScalarFunctionWritables.java

@@ -37,10 +37,13 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.EndsWith;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Hash;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Left;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Locate;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Md5;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Repeat;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Replace;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Reverse;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Right;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Sha1;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Sha256;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Split;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.StartsWith;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Substring;
@@ -79,6 +82,7 @@ public class ScalarFunctionWritables {
         entries.add(Left.ENTRY);
         entries.add(Locate.ENTRY);
         entries.add(Log.ENTRY);
+        entries.add(Md5.ENTRY);
         entries.add(Now.ENTRY);
         entries.add(Or.ENTRY);
         entries.add(Pi.ENTRY);
@@ -88,6 +92,8 @@ public class ScalarFunctionWritables {
         entries.add(Replace.ENTRY);
         entries.add(Reverse.ENTRY);
         entries.add(Round.ENTRY);
+        entries.add(Sha1.ENTRY);
+        entries.add(Sha256.ENTRY);
         entries.add(Split.ENTRY);
         entries.add(Substring.ENTRY);
         entries.add(StartsWith.ENTRY);

+ 70 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/AbstractHashFunction.java

@@ -0,0 +1,70 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.compute.operator.BreakingBytesRefBuilder;
+import org.elasticsearch.compute.operator.DriverContext;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Hash.HashFunction;
+
+import java.io.IOException;
+import java.util.function.Function;
+
+import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
+import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString;
+
+public abstract class AbstractHashFunction extends UnaryScalarFunction {
+
+    protected AbstractHashFunction(Source source, Expression field) {
+        super(source, field);
+    }
+
+    protected AbstractHashFunction(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    protected abstract HashFunction getHashFunction();
+
+    @Override
+    public DataType dataType() {
+        return DataType.KEYWORD;
+    }
+
+    @Override
+    protected TypeResolution resolveType() {
+        if (childrenResolved() == false) {
+            return new TypeResolution("Unresolved children");
+        }
+        return isString(field, sourceText(), DEFAULT);
+    }
+
+    @Override
+    public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
+        return new HashConstantEvaluator.Factory(
+            source(),
+            context -> new BreakingBytesRefBuilder(context.breaker(), "hash"),
+            new Function<>() {
+                @Override
+                public HashFunction apply(DriverContext context) {
+                    return getHashFunction().copy();
+                }
+
+                @Override
+                public String toString() {
+                    return getHashFunction().toString();
+                }
+            },
+            toEvaluator.apply(field)
+        );
+    }
+}

+ 13 - 3
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Hash.java

@@ -21,6 +21,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression;
 import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
 import org.elasticsearch.xpack.esql.core.tree.Source;
 import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.Example;
 import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
 import org.elasticsearch.xpack.esql.expression.function.Param;
 import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlScalarFunction;
@@ -46,7 +47,8 @@ public class Hash extends EsqlScalarFunction {
 
     @FunctionInfo(
         returnType = "keyword",
-        description = "Computes the hash of the input using various algorithms such as MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512."
+        description = "Computes the hash of the input using various algorithms such as MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512.",
+        examples = { @Example(file = "hash", tag = "hash") }
     )
     public Hash(
         Source source,
@@ -186,10 +188,18 @@ public class Hash extends EsqlScalarFunction {
 
     public record HashFunction(String algorithm, MessageDigest digest) {
 
+        public static HashFunction create(String algorithm) {
+            try {
+                return new HashFunction(algorithm, MessageDigest.getInstance(algorithm));
+            } catch (NoSuchAlgorithmException e) {
+                assert false : "Expected to create a valid hashing algorithm";
+                throw new IllegalStateException(e);
+            }
+        }
+
         public static HashFunction create(BytesRef literal) throws NoSuchAlgorithmException {
             var algorithm = literal.utf8ToString();
-            var digest = MessageDigest.getInstance(algorithm);
-            return new HashFunction(algorithm, digest);
+            return new HashFunction(algorithm, MessageDigest.getInstance(algorithm));
         }
 
         public HashFunction copy() {

+ 61 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5.java

@@ -0,0 +1,61 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.Example;
+import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
+import org.elasticsearch.xpack.esql.expression.function.Param;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.Hash.HashFunction;
+
+import java.io.IOException;
+import java.util.List;
+
+public class Md5 extends AbstractHashFunction {
+
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "MD5", Md5::new);
+
+    private static final HashFunction MD5 = HashFunction.create("MD5");
+
+    @FunctionInfo(
+        returnType = "keyword",
+        description = "Computes the MD5 hash of the input.",
+        examples = { @Example(file = "hash", tag = "md5") }
+    )
+    public Md5(Source source, @Param(name = "input", type = { "keyword", "text" }, description = "Input to hash.") Expression input) {
+        super(source, input);
+    }
+
+    private Md5(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    @Override
+    protected HashFunction getHashFunction() {
+        return MD5;
+    }
+
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Md5(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Md5::new, field);
+    }
+}

+ 60 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1.java

@@ -0,0 +1,60 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.Example;
+import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
+import org.elasticsearch.xpack.esql.expression.function.Param;
+
+import java.io.IOException;
+import java.util.List;
+
+public class Sha1 extends AbstractHashFunction {
+
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "SHA1", Sha1::new);
+
+    private static final Hash.HashFunction SHA1 = Hash.HashFunction.create("SHA1");
+
+    @FunctionInfo(
+        returnType = "keyword",
+        description = "Computes the SHA1 hash of the input.",
+        examples = { @Example(file = "hash", tag = "sha1") }
+    )
+    public Sha1(Source source, @Param(name = "input", type = { "keyword", "text" }, description = "Input to hash.") Expression input) {
+        super(source, input);
+    }
+
+    private Sha1(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    @Override
+    protected Hash.HashFunction getHashFunction() {
+        return SHA1;
+    }
+
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Sha1(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Sha1::new, field);
+    }
+}

+ 60 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256.java

@@ -0,0 +1,60 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.Example;
+import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
+import org.elasticsearch.xpack.esql.expression.function.Param;
+
+import java.io.IOException;
+import java.util.List;
+
+public class Sha256 extends AbstractHashFunction {
+
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "SHA256", Sha256::new);
+
+    private static final Hash.HashFunction SHA256 = Hash.HashFunction.create("SHA256");
+
+    @FunctionInfo(
+        returnType = "keyword",
+        description = "Computes the SHA256 hash of the input.",
+        examples = { @Example(file = "hash", tag = "sha256") }
+    )
+    public Sha256(Source source, @Param(name = "input", type = { "keyword", "text" }, description = "Input to hash.") Expression input) {
+        super(source, input);
+    }
+
+    private Sha256(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    @Override
+    protected Hash.HashFunction getHashFunction() {
+        return SHA256;
+    }
+
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Sha256(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Sha256::new, field);
+    }
+}

+ 11 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/HashTests.java

@@ -87,12 +87,22 @@ public class HashTests extends AbstractScalarFunctionTestCase {
         });
     }
 
+    static void addHashFunctionTestCases(List<TestCaseSupplier> cases, String algorithm) {
+        TestCaseSupplier.forUnaryStrings(
+            cases,
+            "HashConstantEvaluator[algorithm=" + algorithm + ", input=Attribute[channel=0]]",
+            DataType.KEYWORD,
+            input -> new BytesRef(HashTests.hash(algorithm, BytesRefs.toString(input))),
+            List.of()
+        );
+    }
+
     private static TestCaseSupplier.TypedData createTypedData(String value, boolean forceLiteral, DataType type, String name) {
         var data = new TestCaseSupplier.TypedData(new BytesRef(value), type, name);
         return forceLiteral ? data.forceLiteral() : data;
     }
 
-    private static String hash(String algorithm, String input) {
+    static String hash(String algorithm, String input) {
         try {
             return HexFormat.of().formatHex(MessageDigest.getInstance(algorithm).digest(input.getBytes(StandardCharsets.UTF_8)));
         } catch (NoSuchAlgorithmException e) {

+ 38 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5ErrorTests.java

@@ -0,0 +1,38 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class Md5ErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
+
+    @Override
+    protected List<TestCaseSupplier> cases() {
+        return paramsToSuppliers(Md5Tests.parameters());
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Md5(source, args.get(0));
+    }
+
+    @Override
+    protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
+        return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
+    }
+}

+ 25 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5SerializationTests.java

@@ -0,0 +1,25 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests;
+
+import java.io.IOException;
+
+public class Md5SerializationTests extends AbstractExpressionSerializationTests<Md5> {
+
+    @Override
+    protected Md5 createTestInstance() {
+        return new Md5(randomSource(), randomChild());
+    }
+
+    @Override
+    protected Md5 mutateInstance(Md5 instance) throws IOException {
+        return new Md5(instance.source(), mutateExpression(instance.field()));
+    }
+}

+ 39 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Md5Tests.java

@@ -0,0 +1,39 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import com.carrotsearch.randomizedtesting.annotations.Name;
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class Md5Tests extends AbstractScalarFunctionTestCase {
+
+    public Md5Tests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
+        this.testCase = testCaseSupplier.get();
+    }
+
+    @ParametersFactory
+    public static Iterable<Object[]> parameters() {
+        List<TestCaseSupplier> cases = new ArrayList<>();
+        HashTests.addHashFunctionTestCases(cases, "MD5");
+        return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases);
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Md5(source, args.get(0));
+    }
+}

+ 38 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1ErrorTests.java

@@ -0,0 +1,38 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class Sha1ErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
+
+    @Override
+    protected List<TestCaseSupplier> cases() {
+        return paramsToSuppliers(Sha1Tests.parameters());
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sha1(source, args.get(0));
+    }
+
+    @Override
+    protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
+        return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
+    }
+}

+ 25 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1SerializationTests.java

@@ -0,0 +1,25 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests;
+
+import java.io.IOException;
+
+public class Sha1SerializationTests extends AbstractExpressionSerializationTests<Sha1> {
+
+    @Override
+    protected Sha1 createTestInstance() {
+        return new Sha1(randomSource(), randomChild());
+    }
+
+    @Override
+    protected Sha1 mutateInstance(Sha1 instance) throws IOException {
+        return new Sha1(instance.source(), mutateExpression(instance.field()));
+    }
+}

+ 39 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha1Tests.java

@@ -0,0 +1,39 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import com.carrotsearch.randomizedtesting.annotations.Name;
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class Sha1Tests extends AbstractScalarFunctionTestCase {
+
+    public Sha1Tests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
+        this.testCase = testCaseSupplier.get();
+    }
+
+    @ParametersFactory
+    public static Iterable<Object[]> parameters() {
+        List<TestCaseSupplier> cases = new ArrayList<>();
+        HashTests.addHashFunctionTestCases(cases, "SHA1");
+        return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases);
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sha1(source, args.get(0));
+    }
+}

+ 38 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256ErrorTests.java

@@ -0,0 +1,38 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class Sha256ErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
+
+    @Override
+    protected List<TestCaseSupplier> cases() {
+        return paramsToSuppliers(Sha256Tests.parameters());
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sha256(source, args.get(0));
+    }
+
+    @Override
+    protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
+        return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
+    }
+}

+ 25 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256SerializationTests.java

@@ -0,0 +1,25 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests;
+
+import java.io.IOException;
+
+public class Sha256SerializationTests extends AbstractExpressionSerializationTests<Sha256> {
+
+    @Override
+    protected Sha256 createTestInstance() {
+        return new Sha256(randomSource(), randomChild());
+    }
+
+    @Override
+    protected Sha256 mutateInstance(Sha256 instance) throws IOException {
+        return new Sha256(instance.source(), mutateExpression(instance.field()));
+    }
+}

+ 39 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Sha256Tests.java

@@ -0,0 +1,39 @@
+/*
+ * 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.expression.function.scalar.string;
+
+import com.carrotsearch.randomizedtesting.annotations.Name;
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class Sha256Tests extends AbstractScalarFunctionTestCase {
+
+    public Sha256Tests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
+        this.testCase = testCaseSupplier.get();
+    }
+
+    @ParametersFactory
+    public static Iterable<Object[]> parameters() {
+        List<TestCaseSupplier> cases = new ArrayList<>();
+        HashTests.addHashFunctionTestCases(cases, "SHA256");
+        return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases);
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sha256(source, args.get(0));
+    }
+}

+ 2 - 2
x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml

@@ -92,7 +92,7 @@ setup:
   - gt: {esql.functions.to_long: $functions_to_long}
   - match: {esql.functions.coalesce: $functions_coalesce}
   # Testing for the entire function set isn't feasbile, so we just check that we return the correct count as an approximation.
-  - length: {esql.functions: 130} # check the "sister" test below for a likely update to the same esql.functions length check
+  - length: {esql.functions: 133} # check the "sister" test below for a likely update to the same esql.functions length check
 
 ---
 "Basic ESQL usage output (telemetry) non-snapshot version":
@@ -163,4 +163,4 @@ setup:
   - match: {esql.functions.cos: $functions_cos}
   - gt: {esql.functions.to_long: $functions_to_long}
   - match: {esql.functions.coalesce: $functions_coalesce}
-  - length: {esql.functions: 126} # check the "sister" test above for a likely update to the same esql.functions length check
+  - length: {esql.functions: 129} # check the "sister" test above for a likely update to the same esql.functions length check