88package org .elasticsearch .xpack .esql .expression .function .fulltext ;
99
1010import org .elasticsearch .xpack .esql .core .expression .Expression ;
11+ import org .elasticsearch .xpack .esql .core .expression .TypeResolutions ;
1112import org .elasticsearch .xpack .esql .core .tree .Source ;
1213import org .elasticsearch .xpack .esql .core .type .DataType ;
14+ import org .elasticsearch .xpack .esql .expression .function .AbstractFunctionTestCase ;
1315import org .elasticsearch .xpack .esql .expression .function .ErrorsForCasesWithoutExamplesTestCase ;
1416import org .elasticsearch .xpack .esql .expression .function .TestCaseSupplier ;
17+ import org .elasticsearch .xpack .esql .expression .predicate .operator .comparison .EsqlBinaryComparison ;
1518import org .hamcrest .Matcher ;
1619
1720import java .util .List ;
21+ import java .util .Locale ;
1822import java .util .Set ;
1923import java .util .stream .Stream ;
2024
25+ import static org .elasticsearch .common .logging .LoggerMessageFormat .format ;
2126import static org .hamcrest .Matchers .equalTo ;
2227
2328public class QueryStringErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
@@ -34,11 +39,42 @@ protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Se
3439
3540 @ Override
3641 protected Expression build (Source source , List <Expression > args ) {
37- return new QueryString (source , args .getFirst (), null );
42+ return new QueryString (source , args .getFirst (), args . size () > 1 ? args . get ( 1 ) : null );
3843 }
3944
4045 @ Override
4146 protected Matcher <String > expectedTypeErrorMatcher (List <Set <DataType >> validPerPosition , List <DataType > signature ) {
42- return equalTo (typeErrorMessage (true , validPerPosition , signature , (v , p ) -> "keyword, text, semantic_text" ));
47+ return equalTo (errorMessageStringForMatch (validPerPosition , signature , (l , p ) -> "keyword, text, semantic_text" ));
48+ }
49+
50+ private static String errorMessageStringForMatch (
51+ List <Set <DataType >> validPerPosition ,
52+ List <DataType > signature ,
53+ AbstractFunctionTestCase .PositionalErrorMessageSupplier positionalErrorMessageSupplier
54+ ) {
55+ boolean invalid = false ;
56+ for (int i = 0 ; i < signature .size () && invalid == false ; i ++) {
57+ // Need to check for nulls and bad parameters in order
58+ if (signature .get (i ) == DataType .NULL ) {
59+ return TypeResolutions .ParamOrdinal .fromIndex (i ).name ().toLowerCase (Locale .ROOT )
60+ + " argument of ["
61+ + sourceForSignature (signature )
62+ + "] cannot be null, received []" ;
63+ }
64+ if (validPerPosition .get (i ).contains (signature .get (i )) == false ) {
65+ // Map expressions have different error messages
66+ if (i == 2 ) {
67+ return format (null , "third argument of [{}] must be a map expression, received []" , sourceForSignature (signature ));
68+ }
69+ break ;
70+ }
71+ }
72+
73+ try {
74+ return typeErrorMessage (true , validPerPosition , signature , positionalErrorMessageSupplier );
75+ } catch (IllegalStateException e ) {
76+ // This means all the positional args were okay, so the expected error is for nulls or from the combination
77+ return EsqlBinaryComparison .formatIncompatibleTypesMessage (signature .get (0 ), signature .get (1 ), sourceForSignature (signature ));
78+ }
4379 }
4480}
0 commit comments