Procházet zdrojové kódy

[ES|QL] Check expression resolved before checking its data type in ImplicitCasting (#113314) (#113626)

* check resolved before check data type
Fang Xing před 1 rokem
rodič
revize
1146344d1e

+ 6 - 0
docs/changelog/113314.yaml

@@ -0,0 +1,6 @@
+pr: 113314
+summary: "[ES|QL] Check expression resolved before checking its data type in `ImplicitCasting`"
+area: ES|QL
+type: bug
+issues:
+ - 113242

+ 20 - 17
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java

@@ -1070,12 +1070,12 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon
         private static Expression processIn(In in) {
             Expression left = in.value();
             List<Expression> right = in.list();
-            DataType targetDataType = left.dataType();
 
-            if (left.resolved() == false || supportsStringImplicitCasting(targetDataType) == false) {
+            if (left.resolved() == false || supportsStringImplicitCasting(left.dataType()) == false) {
                 return in;
             }
 
+            DataType targetDataType = left.dataType();
             List<Expression> newChildren = new ArrayList<>(right.size() + 1);
             boolean childrenChanged = false;
 
@@ -1107,23 +1107,26 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon
             DataType childDataType;
 
             for (Expression e : f.children()) {
-                childDataType = e.dataType();
-                if (childDataType.isNumeric() == false
-                    || childDataType == targetNumericType
-                    || canCastNumeric(childDataType, targetNumericType) == false) {
+                if (e.resolved()) {
+                    childDataType = e.dataType();
+                    if (childDataType.isNumeric() == false
+                        || childDataType == targetNumericType
+                        || canCastNumeric(childDataType, targetNumericType) == false) {
+                        newChildren.add(e);
+                        continue;
+                    }
+                    childrenChanged = true;
+                    // add a casting function
+                    switch (targetNumericType) {
+                        case INTEGER -> newChildren.add(new ToInteger(e.source(), e));
+                        case LONG -> newChildren.add(new ToLong(e.source(), e));
+                        case DOUBLE -> newChildren.add(new ToDouble(e.source(), e));
+                        case UNSIGNED_LONG -> newChildren.add(new ToUnsignedLong(e.source(), e));
+                        default -> throw new EsqlIllegalArgumentException("unexpected data type: " + targetNumericType);
+                    }
+                } else {
                     newChildren.add(e);
-                    continue;
                 }
-                childrenChanged = true;
-                // add a casting function
-                switch (targetNumericType) {
-                    case INTEGER -> newChildren.add(new ToInteger(e.source(), e));
-                    case LONG -> newChildren.add(new ToLong(e.source(), e));
-                    case DOUBLE -> newChildren.add(new ToDouble(e.source(), e));
-                    case UNSIGNED_LONG -> newChildren.add(new ToUnsignedLong(e.source(), e));
-                    default -> throw new EsqlIllegalArgumentException("unexpected data type: " + targetNumericType);
-                }
-
             }
             return childrenChanged ? f.replaceChildren(newChildren) : f;
         }

+ 11 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java

@@ -283,6 +283,17 @@ public class VerifierTests extends ESTestCase {
             "1:42: Cannot convert string [a] to [DOUBLE], error [Cannot parse number [a]]",
             error("ROW a=[3, 5, 1, 6] | EVAL avg_a = MV_AVG(\"a\")")
         );
+        assertEquals(
+            "1:19: Unknown column [languages.*], did you mean any of [languages, languages.byte, languages.long, languages.short]?",
+            error("from test | where `languages.*` in (1, 2)")
+        );
+        assertEquals("1:22: Unknown function [func]", error("from test | eval x = func(languages) | where x in (1, 2)"));
+        assertEquals(
+            "1:32: Unknown column [languages.*], did you mean any of [languages, languages.byte, languages.long, languages.short]?",
+            error("from test | eval x = coalesce( `languages.*`, languages, 0 )")
+        );
+        String error = error("from test | eval x = func(languages) | eval y = coalesce(x, languages, 0 )");
+        assertThat(error, containsString("function [func]"));
     }
 
     public void testAggsExpressionsInStatsAggs() {