Browse Source

Revert "ES|QL: Improve support for TEXT fields in functions (#106688)"

This reverts commit 62e3e5fd1b6f8f3b9902dd8ff24da92f2517ae72.
Luigi Dell'Aquila 1 year ago
parent
commit
720188e95f
24 changed files with 36 additions and 386 deletions
  1. 0 5
      docs/changelog/106688.yaml
  2. 0 7
      docs/reference/esql/functions/description/date_format.asciidoc
  3. 0 14
      docs/reference/esql/functions/layout/date_format.asciidoc
  4. 0 7
      docs/reference/esql/functions/parameters/date_format.asciidoc
  5. 0 1
      docs/reference/esql/functions/signature/date_format.svg
  6. 0 1
      docs/reference/esql/functions/types/date_extract.asciidoc
  7. 0 10
      docs/reference/esql/functions/types/date_format.asciidoc
  8. 0 1
      docs/reference/esql/functions/types/date_parse.asciidoc
  9. 9 9
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/meta.csv-spec
  10. 0 8
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/string.csv-spec
  11. 0 9
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java
  12. 3 4
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateExtract.java
  13. 12 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateFormat.java
  14. 3 4
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateParse.java
  15. 6 5
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java
  16. 3 2
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Split.java
  17. 0 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractFunctionTestCase.java
  18. 0 3
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/AbstractScalarFunctionTestCase.java
  19. 0 12
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateExtractTests.java
  20. 0 79
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateFormatTests.java
  21. 0 12
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateParseTests.java
  22. 0 104
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatchTests.java
  23. 0 61
      x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml
  24. 0 20
      x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/80_text.yml

+ 0 - 5
docs/changelog/106688.yaml

@@ -1,5 +0,0 @@
-pr: 106688
-summary: "ES|QL: Improve support for TEXT fields in functions"
-area: ES|QL
-type: bug
-issues: []

+ 0 - 7
docs/reference/esql/functions/description/date_format.asciidoc

@@ -1,7 +0,0 @@
-// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
-
-*Description*
-
-Returns a string representation of a date, in the provided format.
-
-NOTE: 

+ 0 - 14
docs/reference/esql/functions/layout/date_format.asciidoc

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

+ 0 - 7
docs/reference/esql/functions/parameters/date_format.asciidoc

@@ -1,7 +0,0 @@
-*Parameters*
-
-`dateFormat`::
-A valid date pattern
-
-`date`::
-Date expression

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

@@ -1 +0,0 @@
-<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="516" height="46" viewbox="0 0 516 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 31h5m152 0h10m32 0h10m140 0h10m32 0h10m68 0h10m32 0h5"/><rect class="s" x="5" y="5" width="152" height="36"/><text class="k" x="15" y="31">DATE_FORMAT</text><rect class="s" x="167" y="5" width="32" height="36" rx="7"/><text class="syn" x="177" y="31">(</text><rect class="s" x="209" y="5" width="140" height="36" rx="7"/><text class="k" x="219" y="31">dateFormat</text><rect class="s" x="359" y="5" width="32" height="36" rx="7"/><text class="syn" x="369" y="31">,</text><rect class="s" x="401" y="5" width="68" height="36" rx="7"/><text class="k" x="411" y="31">date</text><rect class="s" x="479" y="5" width="32" height="36" rx="7"/><text class="syn" x="489" y="31">)</text></svg>

+ 0 - 1
docs/reference/esql/functions/types/date_extract.asciidoc

@@ -6,5 +6,4 @@
 |===
 datePart | date | result
 keyword | datetime | long
-text | datetime | long
 |===

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

@@ -1,10 +0,0 @@
-// 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=|]
-|===
-dateFormat | date | result
-keyword | datetime | keyword
-text | datetime | keyword
-|===

+ 0 - 1
docs/reference/esql/functions/types/date_parse.asciidoc

@@ -7,5 +7,4 @@
 datePattern | dateString | result
 keyword | keyword | datetime
 keyword | text | datetime
-text | text | datetime
 |===

+ 9 - 9
x-pack/plugin/esql/qa/testFixtures/src/main/resources/meta.csv-spec

@@ -12,7 +12,7 @@ auto_bucket              |"double|date auto_bucket(field:integer|long|double|dat
 avg                      |"double avg(number:double|integer|long)"                                           |number                     |"double|integer|long"                 |   ""                                               |double                    | "The average of a numeric field."                      | false                | false | true
 case                     |"boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version case(condition:boolean, trueValue...:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version)"                               |[condition, trueValue]             |["boolean", "boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version"]            |["", ""]                                            |"boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version"                    | "Accepts pairs of conditions and values. The function returns the value that belongs to the first condition that evaluates to true."                      | [false, false]       | true | false
 ceil                     |"double|integer|long|unsigned_long ceil(number:double|integer|long|unsigned_long)"     |number                        |"double|integer|long|unsigned_long"                 | "Numeric expression. If `null`, the function returns `null`." | "double|integer|long|unsigned_long"                    | "Round a number up to the nearest integer."                      | false                | false | false
-cidr_match               |"boolean cidr_match(ip:ip, blockX...:keyword|text)"                         |[ip, blockX]             |[ip, "keyword|text"]            |["", "CIDR block to test the IP against."]                                            |boolean                    | "Returns true if the provided IP is contained in one of the provided CIDR blocks."                      | [false, false]       | true | false
+cidr_match               |boolean cidr_match(ip:ip, blockX...:keyword)                         |[ip, blockX]             |[ip, keyword]            |["", "CIDR block to test the IP against."]                                            |boolean                    | "Returns true if the provided IP is contained in one of the provided CIDR blocks."                      | [false, false]       | true | false
 coalesce                 |"boolean|text|integer|keyword|long coalesce(first:boolean|text|integer|keyword|long, ?rest...:boolean|text|integer|keyword|long)"                           |first             | "boolean|text|integer|keyword|long"            | "Expression to evaluate"                                            |"boolean|text|integer|keyword|long"                    | "Returns the first of its arguments that is not null. If all arguments are null, it returns `null`."                      | false       | true | false
 concat                   |"keyword concat(string1:keyword|text, string2...:keyword|text)"                             |[string1, string2]             |["keyword|text", "keyword|text"]            |["", ""]                                            |keyword                    | "Concatenates two or more strings."                      | [false, false]       | true | false
 cos                      |"double cos(number:double|integer|long|unsigned_long)"      |number             |"double|integer|long|unsigned_long"                 | "An angle, in radians"  |double         | "Returns the trigonometric cosine of an angle"                      | false                | false | false
@@ -20,10 +20,10 @@ cosh                     |"double cosh(number:double|integer|long|unsigned_long)
 count                    |"long count(?field:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version)"                                         |field                     |"boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version"                 | "Column or literal for which to count the number of values."                                                 |long                    | "Returns the total number (count) of input values."                      | true                | false | true
 count_distinct           |"long count_distinct(field:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|version, ?precision:integer)"                        |[field, precision]             |["boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|version, integer"]            |["Column or literal for which to count the number of distinct values.", ""]                                            |long                    | "Returns the approximate number of distinct values."                      | [false, true]       | false | true
 date_diff                |"integer date_diff(unit:keyword|text, startTimestamp:date, endTimestamp:date)"|[unit, startTimestamp, endTimestamp] |["keyword|text", "date", "date"]  |["A valid date unit", "A string representing a start timestamp", "A string representing an end timestamp"] |integer | "Subtract 2 dates and return their difference in multiples of a unit specified in the 1st argument" | [false, false, false] | false | false
-date_extract             |"long date_extract(datePart:keyword|text, date:date)"                          |[datePart, date]             |["keyword|text", date]            |["Part of the date to extract. Can be: aligned_day_of_week_in_month; aligned_day_of_week_in_year; aligned_week_of_month; aligned_week_of_year; ampm_of_day; clock_hour_of_ampm; clock_hour_of_day; day_of_month; day_of_week; day_of_year; epoch_day; era; hour_of_ampm; hour_of_day; instant_seconds; micro_of_day; micro_of_second; milli_of_day; milli_of_second; minute_of_day; minute_of_hour; month_of_year; nano_of_day; nano_of_second; offset_seconds; proleptic_month; second_of_day; second_of_minute; year; or year_of_era.", "Date expression"]                                            |long                    | "Extracts parts of a date, like year, month, day, hour."                      | [false, false]       | false | false
-date_format              |"keyword date_format(?dateFormat:keyword|text, date:date)"                           |[dateFormat, date]             |["keyword|text", date]            |["A valid date pattern", "Date expression"]                                            |keyword                    | "Returns a string representation of a date, in the provided format."                      | [true, false]       | false | false
-date_parse               |"date date_parse(?datePattern:keyword|text, dateString:keyword|text)"|[datePattern, dateString]|["keyword|text", "keyword|text"]|["A valid date pattern", "A string representing a date"]|date                 |Parses a string into a date value | [true, false]       | false          | false
-date_trunc               |"date date_trunc(interval:keyword, date:date)"                            |[interval, date]             |["keyword", date]            |["Interval; expressed using the timespan literal syntax.", "Date expression"]                                            |date                    | "Rounds down a date to the closest interval."                      | [false, false]       | false | false
+date_extract             |long date_extract(datePart:keyword, date:date)                          |[datePart, date]             |[keyword, date]            |["Part of the date to extract. Can be: aligned_day_of_week_in_month; aligned_day_of_week_in_year; aligned_week_of_month; aligned_week_of_year; ampm_of_day; clock_hour_of_ampm; clock_hour_of_day; day_of_month; day_of_week; day_of_year; epoch_day; era; hour_of_ampm; hour_of_day; instant_seconds; micro_of_day; micro_of_second; milli_of_day; milli_of_second; minute_of_day; minute_of_hour; month_of_year; nano_of_day; nano_of_second; offset_seconds; proleptic_month; second_of_day; second_of_minute; year; or year_of_era.", "Date expression"]                                            |long                    | "Extracts parts of a date, like year, month, day, hour."                      | [false, false]       | false | false
+date_format              |keyword date_format(?dateFormat:keyword, date:date)                           |[dateFormat, date]             |[keyword, date]            |["A valid date pattern", "Date expression"]                                            |keyword                    | "Returns a string representation of a date, in the provided format."                      | [true, false]       | false | false
+date_parse               |"date date_parse(?datePattern:keyword, dateString:keyword|text)"|[datePattern, dateString]|["keyword", "keyword|text"]|["A valid date pattern", "A string representing a date"]|date                 |Parses a string into a date value | [true, false]       | false          | false
+date_trunc               |"date date_trunc(interval:keyword, date:date)"                            |[interval, date]             |[keyword, date]            |["Interval; expressed using the timespan literal syntax.", "Date expression"]                                            |date                    | "Rounds down a date to the closest interval."                      | [false, false]       | false | false
 e                        |double e()                                                   | null                    | null             | null                                               |double                    | "Euler’s number."                      | null                 | false | false
 ends_with                |"boolean ends_with(str:keyword|text, suffix:keyword|text)"                             |[str, suffix]             |["keyword|text", "keyword|text"]            |["", ""]                                            |boolean                    | "Returns a boolean that indicates whether a keyword string ends with another string"                      | [false, false]       | false | false
 floor                    |"double|integer|long|unsigned_long floor(number:double|integer|long|unsigned_long)"    |number                       |"double|integer|long|unsigned_long"    | ""                                                 |"double|integer|long|unsigned_long"                    | "Round a number down to the nearest integer."                      | false                | false | false
@@ -116,7 +116,7 @@ synopsis:keyword
 "double avg(number:double|integer|long)"
 "boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version case(condition:boolean, trueValue...:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version)"
 "double|integer|long|unsigned_long ceil(number:double|integer|long|unsigned_long)"
-"boolean cidr_match(ip:ip, blockX...:keyword|text)"
+boolean cidr_match(ip:ip, blockX...:keyword)
 "boolean|text|integer|keyword|long coalesce(first:boolean|text|integer|keyword|long, ?rest...:boolean|text|integer|keyword|long)"
 "keyword concat(string1:keyword|text, string2...:keyword|text)"
 "double cos(number:double|integer|long|unsigned_long)"
@@ -124,9 +124,9 @@ synopsis:keyword
 "long count(?field:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|unsigned_long|version)"
 "long count_distinct(field:boolean|cartesian_point|date|double|geo_point|integer|ip|keyword|long|text|version, ?precision:integer)"
 "integer date_diff(unit:keyword|text, startTimestamp:date, endTimestamp:date)"
-"long date_extract(datePart:keyword|text, date:date)"
-"keyword date_format(?dateFormat:keyword|text, date:date)"
-"date date_parse(?datePattern:keyword|text, dateString:keyword|text)"
+long date_extract(datePart:keyword, date:date)
+keyword date_format(?dateFormat:keyword, date:date)
+"date date_parse(?datePattern:keyword, dateString:keyword|text)"
 "date date_trunc(interval:keyword, date:date)"
 double e()
 "boolean ends_with(str:keyword|text, suffix:keyword|text)"

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

@@ -1160,11 +1160,3 @@ required_feature: esql.agg_values
                                                                                              null | null
 // end::values-grouped-result[]
 ;
-
-
-splitBasedOnField
-from employees | where emp_no == 10001 | eval split = split("fooMbar", gender) | keep gender, split;
-
-gender:keyword | split:keyword 
-M              | [foo, bar]
-;

+ 0 - 9
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java

@@ -27,15 +27,6 @@ import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isType;
 
 public class EsqlTypeResolutions {
 
-    public static Expression.TypeResolution isStringAndExact(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) {
-        Expression.TypeResolution resolution = TypeResolutions.isString(e, operationName, paramOrd);
-        if (resolution.unresolved()) {
-            return resolution;
-        }
-
-        return isExact(e, operationName, paramOrd);
-    }
-
     public static Expression.TypeResolution isExact(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) {
         if (e instanceof FieldAttribute fa) {
             if (DataTypes.isString(fa.dataType())) {

+ 3 - 4
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateExtract.java

@@ -14,7 +14,6 @@ import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator;
 import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
 import org.elasticsearch.xpack.esql.expression.function.Param;
 import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlConfigurationFunction;
-import org.elasticsearch.xpack.esql.type.EsqlDataTypes;
 import org.elasticsearch.xpack.ql.InvalidArgumentException;
 import org.elasticsearch.xpack.ql.expression.Expression;
 import org.elasticsearch.xpack.ql.expression.TypeResolutions;
@@ -29,10 +28,10 @@ import java.time.temporal.ChronoField;
 import java.util.List;
 import java.util.function.Function;
 
-import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.EsqlConverter.STRING_TO_CHRONO_FIELD;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.chronoToLong;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact;
 
 public class DateExtract extends EsqlConfigurationFunction {
 
@@ -43,7 +42,7 @@ public class DateExtract extends EsqlConfigurationFunction {
         Source source,
         // Need to replace the commas in the description here with semi-colon as there's a bug in the CSV parser
         // used in the CSVTests and fixing it is not trivial
-        @Param(name = "datePart", type = { "keyword", "text" }, description = """
+        @Param(name = "datePart", type = { "keyword" }, description = """
             Part of the date to extract.
             Can be: aligned_day_of_week_in_month; aligned_day_of_week_in_year; aligned_week_of_month;
             aligned_week_of_year; ampm_of_day; clock_hour_of_ampm; clock_hour_of_day; day_of_month; day_of_week;
@@ -77,7 +76,7 @@ public class DateExtract extends EsqlConfigurationFunction {
         if (chronoField == null) {
             Expression field = children().get(0);
             try {
-                if (field.foldable() && EsqlDataTypes.isString(field.dataType())) {
+                if (field.foldable() && field.dataType() == DataTypes.KEYWORD) {
                     chronoField = (ChronoField) STRING_TO_CHRONO_FIELD.convert(field.fold());
                 }
             } catch (Exception e) {

+ 12 - 7
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateFormat.java

@@ -16,7 +16,6 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
 import org.elasticsearch.xpack.esql.expression.function.Param;
 import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlConfigurationFunction;
 import org.elasticsearch.xpack.esql.session.EsqlConfiguration;
-import org.elasticsearch.xpack.esql.type.EsqlDataTypes;
 import org.elasticsearch.xpack.ql.expression.Expression;
 import org.elasticsearch.xpack.ql.expression.function.OptionalArgument;
 import org.elasticsearch.xpack.ql.session.Configuration;
@@ -29,12 +28,12 @@ import java.util.List;
 import java.util.Locale;
 import java.util.function.Function;
 
-import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.DEFAULT_DATE_TIME_FORMATTER;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.FIRST;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.SECOND;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact;
 
 public class DateFormat extends EsqlConfigurationFunction implements OptionalArgument {
 
@@ -44,7 +43,7 @@ public class DateFormat extends EsqlConfigurationFunction implements OptionalArg
     @FunctionInfo(returnType = "keyword", description = "Returns a string representation of a date, in the provided format.")
     public DateFormat(
         Source source,
-        @Param(optional = true, name = "dateFormat", type = { "keyword", "text" }, description = "A valid date pattern") Expression format,
+        @Param(optional = true, name = "dateFormat", type = { "keyword" }, description = "A valid date pattern") Expression format,
         @Param(name = "date", type = { "date" }, description = "Date expression") Expression date,
         Configuration configuration
     ) {
@@ -97,17 +96,23 @@ public class DateFormat extends EsqlConfigurationFunction implements OptionalArg
     public ExpressionEvaluator.Factory toEvaluator(Function<Expression, ExpressionEvaluator.Factory> toEvaluator) {
         var fieldEvaluator = toEvaluator.apply(field);
         if (format == null) {
-            return new DateFormatConstantEvaluator.Factory(source(), fieldEvaluator, DEFAULT_DATE_TIME_FORMATTER);
+            return dvrCtx -> new DateFormatConstantEvaluator(source(), fieldEvaluator.get(dvrCtx), DEFAULT_DATE_TIME_FORMATTER, dvrCtx);
         }
-        if (EsqlDataTypes.isString(format.dataType()) == false) {
+        if (format.dataType() != DataTypes.KEYWORD) {
             throw new IllegalArgumentException("unsupported data type for format [" + format.dataType() + "]");
         }
         if (format.foldable()) {
             DateFormatter formatter = toFormatter(format.fold(), ((EsqlConfiguration) configuration()).locale());
-            return new DateFormatConstantEvaluator.Factory(source(), fieldEvaluator, formatter);
+            return dvrCtx -> new DateFormatConstantEvaluator(source(), fieldEvaluator.get(dvrCtx), formatter, dvrCtx);
         }
         var formatEvaluator = toEvaluator.apply(format);
-        return new DateFormatEvaluator.Factory(source(), fieldEvaluator, formatEvaluator, ((EsqlConfiguration) configuration()).locale());
+        return dvrCtx -> new DateFormatEvaluator(
+            source(),
+            fieldEvaluator.get(dvrCtx),
+            formatEvaluator.get(dvrCtx),
+            ((EsqlConfiguration) configuration()).locale(),
+            dvrCtx
+        );
     }
 
     private static DateFormatter toFormatter(Object format, Locale locale) {

+ 3 - 4
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateParse.java

@@ -15,7 +15,6 @@ import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator;
 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;
-import org.elasticsearch.xpack.esql.type.EsqlDataTypes;
 import org.elasticsearch.xpack.ql.InvalidArgumentException;
 import org.elasticsearch.xpack.ql.expression.Expression;
 import org.elasticsearch.xpack.ql.expression.function.OptionalArgument;
@@ -29,12 +28,12 @@ import java.util.List;
 import java.util.function.Function;
 
 import static org.elasticsearch.common.time.DateFormatter.forPattern;
-import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.DEFAULT_DATE_TIME_FORMATTER;
 import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToLong;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.FIRST;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.SECOND;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.ql.util.DateUtils.UTC;
 
 public class DateParse extends EsqlScalarFunction implements OptionalArgument {
@@ -45,7 +44,7 @@ public class DateParse extends EsqlScalarFunction implements OptionalArgument {
     @FunctionInfo(returnType = "date", description = "Parses a string into a date value")
     public DateParse(
         Source source,
-        @Param(name = "datePattern", type = { "keyword", "text" }, description = "A valid date pattern", optional = true) Expression first,
+        @Param(name = "datePattern", type = { "keyword" }, description = "A valid date pattern", optional = true) Expression first,
         @Param(name = "dateString", type = { "keyword", "text" }, description = "A string representing a date") Expression second
     ) {
         super(source, second != null ? List.of(first, second) : List.of(first));
@@ -100,7 +99,7 @@ public class DateParse extends EsqlScalarFunction implements OptionalArgument {
         if (format == null) {
             return new DateParseConstantEvaluator.Factory(source(), fieldEvaluator, DEFAULT_DATE_TIME_FORMATTER);
         }
-        if (EsqlDataTypes.isString(format.dataType()) == false) {
+        if (format.dataType() != DataTypes.KEYWORD) {
             throw new IllegalArgumentException("unsupported data type for date_parse [" + format.dataType() + "]");
         }
         if (format.foldable()) {

+ 6 - 5
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java

@@ -28,10 +28,10 @@ import java.util.List;
 import java.util.function.Function;
 
 import static java.util.Collections.singletonList;
-import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.FIRST;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.fromIndex;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isIPAndExact;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact;
 
 /**
  * This function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specification:
@@ -53,7 +53,7 @@ public class CIDRMatch extends EsqlScalarFunction {
     public CIDRMatch(
         Source source,
         @Param(name = "ip", type = { "ip" }) Expression ipField,
-        @Param(name = "blockX", type = { "keyword", "text" }, description = "CIDR block to test the IP against.") List<Expression> matches
+        @Param(name = "blockX", type = { "keyword" }, description = "CIDR block to test the IP against.") List<Expression> matches
     ) {
         super(source, CollectionUtils.combine(singletonList(ipField), matches));
         this.ipField = ipField;
@@ -76,10 +76,11 @@ public class CIDRMatch extends EsqlScalarFunction {
     @Override
     public ExpressionEvaluator.Factory toEvaluator(Function<Expression, ExpressionEvaluator.Factory> toEvaluator) {
         var ipEvaluatorSupplier = toEvaluator.apply(ipField);
-        return new CIDRMatchEvaluator.Factory(
+        return dvrCtx -> new CIDRMatchEvaluator(
             source(),
-            ipEvaluatorSupplier,
-            matches.stream().map(x -> toEvaluator.apply(x)).toArray(EvalOperator.ExpressionEvaluator.Factory[]::new)
+            ipEvaluatorSupplier.get(dvrCtx),
+            matches.stream().map(x -> toEvaluator.apply(x).get(dvrCtx)).toArray(EvalOperator.ExpressionEvaluator[]::new),
+            dvrCtx
         );
     }
 

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

@@ -25,9 +25,10 @@ import org.elasticsearch.xpack.ql.type.DataTypes;
 
 import java.util.function.Function;
 
-import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isStringAndExact;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.FIRST;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.SECOND;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact;
 
 /**
  * Splits a string on some delimiter into a multivalued string field.
@@ -58,7 +59,7 @@ public class Split extends BinaryScalarFunction implements EvaluatorMapper {
             return resolution;
         }
 
-        return isStringAndExact(right(), sourceText(), SECOND);
+        return isString(right(), sourceText(), SECOND);
     }
 
     @Override

+ 0 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractFunctionTestCase.java

@@ -896,7 +896,6 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
         ),
         Map.entry(Set.of(DataTypes.DOUBLE, DataTypes.NULL), "double"),
         Map.entry(Set.of(DataTypes.INTEGER, DataTypes.NULL), "integer"),
-        Map.entry(Set.of(DataTypes.IP, DataTypes.NULL), "ip"),
         Map.entry(Set.of(DataTypes.LONG, DataTypes.INTEGER, DataTypes.UNSIGNED_LONG, DataTypes.DOUBLE, DataTypes.NULL), "numeric"),
         Map.entry(Set.of(DataTypes.KEYWORD, DataTypes.TEXT, DataTypes.VERSION, DataTypes.NULL), "string or version"),
         Map.entry(Set.of(DataTypes.KEYWORD, DataTypes.TEXT, DataTypes.NULL), "string"),

+ 0 - 3
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/AbstractScalarFunctionTestCase.java

@@ -177,9 +177,6 @@ public abstract class AbstractScalarFunctionTestCase extends AbstractFunctionTes
         if (withoutNull.equals(List.of(DataTypes.DATETIME))) {
             return "datetime";
         }
-        if (withoutNull.equals(List.of(DataTypes.IP))) {
-            return "ip";
-        }
         List<DataType> negations = Stream.concat(Stream.of(numerics()), Stream.of(EsqlDataTypes.DATE_PERIOD, EsqlDataTypes.TIME_DURATION))
             .sorted(Comparator.comparing(DataType::name))
             .toList();

+ 0 - 12
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateExtractTests.java

@@ -53,18 +53,6 @@ public class DateExtractTests extends AbstractScalarFunctionTestCase {
                         equalTo(2023L)
                     )
                 ),
-                new TestCaseSupplier(
-                    List.of(DataTypes.TEXT, DataTypes.DATETIME),
-                    () -> new TestCaseSupplier.TestCase(
-                        List.of(
-                            new TestCaseSupplier.TypedData(new BytesRef("YeAr"), DataTypes.TEXT, "chrono"),
-                            new TestCaseSupplier.TypedData(1687944333000L, DataTypes.DATETIME, "date")
-                        ),
-                        "DateExtractEvaluator[value=Attribute[channel=1], chronoField=Attribute[channel=0], zone=Z]",
-                        DataTypes.LONG,
-                        equalTo(2023L)
-                    )
-                ),
                 new TestCaseSupplier(
                     List.of(DataTypes.KEYWORD, DataTypes.DATETIME),
                     () -> new TestCaseSupplier.TestCase(

+ 0 - 79
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateFormatTests.java

@@ -1,79 +0,0 @@
-/*
- * 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.date;
-
-import com.carrotsearch.randomizedtesting.annotations.Name;
-import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
-
-import org.apache.lucene.util.BytesRef;
-import org.elasticsearch.common.lucene.BytesRefs;
-import org.elasticsearch.xpack.esql.EsqlTestUtils;
-import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
-import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
-import org.elasticsearch.xpack.ql.expression.Expression;
-import org.elasticsearch.xpack.ql.tree.Source;
-import org.elasticsearch.xpack.ql.type.DataType;
-import org.elasticsearch.xpack.ql.type.DataTypes;
-
-import java.util.List;
-import java.util.function.Supplier;
-
-import static org.hamcrest.Matchers.equalTo;
-
-public class DateFormatTests extends AbstractScalarFunctionTestCase {
-    public DateFormatTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
-        this.testCase = testCaseSupplier.get();
-    }
-
-    @ParametersFactory
-    public static Iterable<Object[]> parameters() {
-        return parameterSuppliersFromTypedData(
-            List.of(
-                new TestCaseSupplier(
-                    List.of(DataTypes.KEYWORD, DataTypes.DATETIME),
-                    () -> new TestCaseSupplier.TestCase(
-                        List.of(
-                            new TestCaseSupplier.TypedData(new BytesRef("yyyy"), DataTypes.KEYWORD, "formatter"),
-                            new TestCaseSupplier.TypedData(1687944333000L, DataTypes.DATETIME, "val")
-                        ),
-                        "DateFormatEvaluator[val=Attribute[channel=1], formatter=Attribute[channel=0], locale=en_US]",
-                        DataTypes.KEYWORD,
-                        equalTo(BytesRefs.toBytesRef("2023"))
-                    )
-                ),
-                new TestCaseSupplier(
-                    List.of(DataTypes.TEXT, DataTypes.DATETIME),
-                    () -> new TestCaseSupplier.TestCase(
-                        List.of(
-                            new TestCaseSupplier.TypedData(new BytesRef("yyyy"), DataTypes.TEXT, "formatter"),
-                            new TestCaseSupplier.TypedData(1687944333000L, DataTypes.DATETIME, "val")
-                        ),
-                        "DateFormatEvaluator[val=Attribute[channel=1], formatter=Attribute[channel=0], locale=en_US]",
-                        DataTypes.KEYWORD,
-                        equalTo(BytesRefs.toBytesRef("2023"))
-                    )
-                )
-            )
-        );
-    }
-
-    @Override
-    protected Expression build(Source source, List<Expression> args) {
-        return new DateFormat(source, args.get(0), args.get(1), EsqlTestUtils.TEST_CFG);
-    }
-
-    @Override
-    protected List<ArgumentSpec> argSpec() {
-        return List.of(required(strings()), required(DataTypes.DATETIME));
-    }
-
-    @Override
-    protected DataType expectedType(List<DataType> argTypes) {
-        return DataTypes.KEYWORD;
-    }
-}

+ 0 - 12
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DateParseTests.java

@@ -62,18 +62,6 @@ public class DateParseTests extends AbstractScalarFunctionTestCase {
                         equalTo(1683244800000L)
                     )
                 ),
-                new TestCaseSupplier(
-                    "With Both Text",
-                    () -> new TestCaseSupplier.TestCase(
-                        List.of(
-                            new TestCaseSupplier.TypedData(new BytesRef("yyyy-MM-dd"), DataTypes.TEXT, "second"),
-                            new TestCaseSupplier.TypedData(new BytesRef("2023-05-05"), DataTypes.TEXT, "first")
-                        ),
-                        "DateParseEvaluator[val=Attribute[channel=1], formatter=Attribute[channel=0], zoneId=Z]",
-                        DataTypes.DATETIME,
-                        equalTo(1683244800000L)
-                    )
-                ),
                 new TestCaseSupplier(
                     List.of(DataTypes.KEYWORD, DataTypes.KEYWORD),
                     () -> new TestCaseSupplier.TestCase(

+ 0 - 104
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatchTests.java

@@ -1,104 +0,0 @@
-/*
- * 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.ip;
-
-import com.carrotsearch.randomizedtesting.annotations.Name;
-import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
-
-import org.apache.lucene.util.BytesRef;
-import org.elasticsearch.common.lucene.BytesRefs;
-import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
-import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
-import org.elasticsearch.xpack.ql.expression.Expression;
-import org.elasticsearch.xpack.ql.tree.Source;
-import org.elasticsearch.xpack.ql.type.DataType;
-import org.elasticsearch.xpack.ql.type.DataTypes;
-
-import java.util.List;
-import java.util.function.Supplier;
-
-import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.EsqlConverter.STRING_TO_IP;
-import static org.hamcrest.Matchers.equalTo;
-
-public class CIDRMatchTests extends AbstractScalarFunctionTestCase {
-    public CIDRMatchTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
-        this.testCase = testCaseSupplier.get();
-    }
-
-    @ParametersFactory
-    public static Iterable<Object[]> parameters() {
-
-        var suppliers = List.of(
-            new TestCaseSupplier(
-                List.of(DataTypes.IP, DataTypes.KEYWORD),
-                () -> new TestCaseSupplier.TestCase(
-                    List.of(
-                        new TestCaseSupplier.TypedData(STRING_TO_IP.convert(BytesRefs.toBytesRef("192.168.0.10")), DataTypes.IP, "ip"),
-                        new TestCaseSupplier.TypedData(new BytesRef("192.168.0.0/16"), DataTypes.KEYWORD, "cidrs")
-                    ),
-                    "CIDRMatchEvaluator[ip=Attribute[channel=0], cidrs=[Attribute[channel=1]]]",
-                    DataTypes.BOOLEAN,
-                    equalTo(true)
-                )
-            ),
-            new TestCaseSupplier(
-                List.of(DataTypes.IP, DataTypes.TEXT),
-                () -> new TestCaseSupplier.TestCase(
-                    List.of(
-                        new TestCaseSupplier.TypedData(STRING_TO_IP.convert(BytesRefs.toBytesRef("192.168.0.10")), DataTypes.IP, "ip"),
-                        new TestCaseSupplier.TypedData(new BytesRef("192.168.0.0/16"), DataTypes.TEXT, "cidrs")
-                    ),
-                    "CIDRMatchEvaluator[ip=Attribute[channel=0], cidrs=[Attribute[channel=1]]]",
-                    DataTypes.BOOLEAN,
-                    equalTo(true)
-                )
-            ),
-            new TestCaseSupplier(
-                List.of(DataTypes.IP, DataTypes.KEYWORD),
-                () -> new TestCaseSupplier.TestCase(
-                    List.of(
-                        new TestCaseSupplier.TypedData(STRING_TO_IP.convert(BytesRefs.toBytesRef("192.168.0.10")), DataTypes.IP, "ip"),
-                        new TestCaseSupplier.TypedData(new BytesRef("10.0.0.0/16"), DataTypes.KEYWORD, "cidrs")
-                    ),
-                    "CIDRMatchEvaluator[ip=Attribute[channel=0], cidrs=[Attribute[channel=1]]]",
-                    DataTypes.BOOLEAN,
-                    equalTo(false)
-                )
-            ),
-            new TestCaseSupplier(
-                List.of(DataTypes.IP, DataTypes.TEXT),
-                () -> new TestCaseSupplier.TestCase(
-                    List.of(
-                        new TestCaseSupplier.TypedData(STRING_TO_IP.convert(BytesRefs.toBytesRef("192.168.0.10")), DataTypes.IP, "ip"),
-                        new TestCaseSupplier.TypedData(new BytesRef("10.0.0.0/16"), DataTypes.TEXT, "cidrs")
-                    ),
-                    "CIDRMatchEvaluator[ip=Attribute[channel=0], cidrs=[Attribute[channel=1]]]",
-                    DataTypes.BOOLEAN,
-                    equalTo(false)
-                )
-            )
-        );
-
-        return parameterSuppliersFromTypedData(errorsForCasesWithoutExamples(anyNullIsNull(true, suppliers)));
-    }
-
-    @Override
-    protected Expression build(Source source, List<Expression> args) {
-        return new CIDRMatch(source, args.get(0), List.of(args.get(1)));
-    }
-
-    @Override
-    protected List<ArgumentSpec> argSpec() {
-        return List.of(required(DataTypes.IP), required(strings()));
-    }
-
-    @Override
-    protected DataType expectedType(List<DataType> argTypes) {
-        return DataTypes.BOOLEAN;
-    }
-}

+ 0 - 61
x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml

@@ -193,64 +193,3 @@
   - match: { columns.0.type: double }
   - length: { values: 1 }
   - match: { values.0.0: 30.0 }
-
-
-
----
-"text in functions #105379":
-  - skip:
-      version: " - 8.13.99"
-      reason: "fixes in 8.13 or later"
-  - do:
-      indices.create:
-        index: idx_with_date_ip_txt
-        body:
-          mappings:
-            properties:
-              id:
-                type: long
-              date:
-                type: date
-              ip:
-                type: ip
-              text:
-                type: text
-              text2:
-                type: text
-
-  - do:
-      bulk:
-        refresh: true
-        body:
-          - { "index": { "_index": "idx_with_date_ip_txt" } }
-          - { "id": 1, "date": "2024-03-22T14:50:00.000Z", "ip": "192.168.0.10", "text":"yyyy-MM-dd", "text2":"year" }
-          - { "index": { "_index": "idx_with_date_ip_txt" } }
-          - { "id": 2, "date": "2024-03-22T14:50:00.000Z", "ip": "192.168.0.10", "text": "192.168.0.0/16" }
-          - { "index": { "_index": "idx_with_date_ip_txt" } }
-          - { "id": 3, "date": "2024-03-22T14:50:00.000Z", "ip": "10.0.0.10", "text": "192.168.0.0/16" }
-  - do:
-      esql.query:
-        body:
-          query: 'from idx_with_date_ip_txt | where id == 1 | eval x = date_format(text, date), y = date_extract(text2, date), p = date_parse(text, "2024-03-14") | keep x, y, p | limit 1'
-  - match: { columns.0.name: x }
-  - match: { columns.0.type: keyword }
-  - match: { columns.1.name: y }
-  - match: { columns.1.type: long }
-  - length: { values: 1 }
-  - match: { values.0.0: "2024-03-22" }
-  - match: { values.0.1: 2024 }
-  - match: { values.0.2: "2024-03-14T00:00:00.000Z" }
-
-  - do:
-      esql.query:
-        body:
-          query: 'from idx_with_date_ip_txt | where id > 1 | eval x = cidr_match(ip, text) | sort id | keep id, x | limit 2'
-  - match: { columns.0.name: id }
-  - match: { columns.0.type: long }
-  - match: { columns.1.name: x }
-  - match: { columns.1.type: boolean }
-  - length: { values: 2 }
-  - match: { values.0.0: 2 }
-  - match: { values.0.1: true }
-  - match: { values.1.0: 3 }
-  - match: { values.1.1: false }

+ 0 - 20
x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/80_text.yml

@@ -366,26 +366,6 @@ setup:
   - match: { values.0: [ "Jenny - IT Director"] }
   - match: { values.1: [ "John - Payroll Specialist"] }
 
----
-"split text":
-  - skip:
-      version: " - 8.13.99"
-      reason: "functions fixed for text in v 8.14"
-      features: allowed_warnings_regex
-  - do:
-      allowed_warnings_regex:
-        - "No limit defined, adding default limit of \\[.*\\]"
-      esql.query:
-        body:
-          query: 'from test | sort emp_no | eval split = split(tag, " ") | keep split'
-
-  - match: { columns.0.name: "split" }
-  - match: { columns.0.type: "keyword" }
-
-  - length: { values: 2 }
-  - match: { values.0: [ ["foo", "bar"] ] }
-  - match: { values.1: [ "baz"] }
-
 
 ---
 "stats text with raw":