You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by GitBox <gi...@apache.org> on 2022/06/15 13:26:59 UTC

[GitHub] [incubator-doris] Userwhite commented on a diff in pull request #9895: [Enhancement](DOE) Step1: Fe generates the DSL and is used to explain

Userwhite commented on code in PR #9895:
URL: https://github.com/apache/incubator-doris/pull/9895#discussion_r897970720


##########
fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java:
##########
@@ -87,12 +106,156 @@ public static JSONObject getJsonObject(JSONObject jsonObject, String key, int fr
         }
     }
 
+    /**
+     * Wrapper for get boolean value.
+     **/
     public static boolean getBoolean(Map<String, String> properties, String name) throws DdlException {
         String property = properties.get(name).trim();
         try {
             return Boolean.parseBoolean(property);
         } catch (Exception e) {
-            throw new DdlException(String.format("fail to parse %s, %s = %s, `%s` should be like 'true' or 'false', value should be double quotation marks", name, name, property, name));
+            throw new DdlException(String.format("fail to parse %s, %s = %s, `%s` should be like 'true' or 'false', "
+                    + "value should be double quotation marks", name, name, property, name));
+        }
+    }
+
+    /**
+     * Doris expr to es dsl.
+     **/
+    public static QueryBuilder convertToEsDsl(Expr expr) {
+        if (expr == null) {
+            return null;
+        }
+        // CompoundPredicate, `between` also converted to CompoundPredicate.
+        if (expr instanceof CompoundPredicate) {
+            CompoundPredicate compoundPredicate = (CompoundPredicate) expr;
+            switch (compoundPredicate.getOp()) {
+                case AND: {
+                    QueryBuilder left = convertToEsDsl(compoundPredicate.getChild(0));
+                    QueryBuilder right = convertToEsDsl(compoundPredicate.getChild(1));
+                    if (left != null && right != null) {
+                        return QueryBuilders.boolQuery().must(left).must(right);
+                    }
+                    return null;
+                }
+                case OR: {
+                    QueryBuilder left = convertToEsDsl(compoundPredicate.getChild(0));
+                    QueryBuilder right = convertToEsDsl(compoundPredicate.getChild(1));
+                    if (left != null && right != null) {
+                        return QueryBuilders.boolQuery().should(left).should(right);
+                    }
+                    return null;
+                }
+                case NOT: {
+                    QueryBuilder child = convertToEsDsl(compoundPredicate.getChild(0));
+                    if (child != null) {
+                        return QueryBuilders.boolQuery().mustNot(child);
+                    }
+                    return null;
+                }
+                default:
+                    return null;
+            }
+        }
+        TExprOpcode opCode = expr.getOpcode();
+        String column = ((SlotRef) expr.getChild(0)).getColumnName();
+        if (expr instanceof BinaryPredicate) {
+            Object value = extractDorisLiteral(expr.getChild(1));
+            switch (opCode) {
+                case EQ:
+                    return QueryBuilders.termQuery(column, value);
+                case NE:
+                    return QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(column, value));
+                case GE:
+                    return QueryBuilders.rangeQuery(column).gte(value);
+                case GT:
+                    return QueryBuilders.rangeQuery(column).gt(value);
+                case LE:
+                    return QueryBuilders.rangeQuery(column).lte(value);
+                case LT:
+                    return QueryBuilders.rangeQuery(column).lt(value);
+                case EQ_FOR_NULL:
+                    return QueryBuilders.termQuery(column, value);
+                default:
+                    return null;
+            }
+        }
+        if (expr instanceof IsNullPredicate) {
+            IsNullPredicate isNullPredicate = (IsNullPredicate) expr;
+            if (isNullPredicate.isNotNull()) {
+                return QueryBuilders.existsQuery(column);
+            }
+            return QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(column));
+        }
+        if (expr instanceof LikePredicate) {
+            LikePredicate likePredicate = (LikePredicate) expr;
+            if (likePredicate.getOp().equals(Operator.LIKE)) {
+                char[] chars = likePredicate.getChild(1).getStringValue().toCharArray();
+                // example of translation :
+                //      abc_123  ===> abc?123
+                //      abc%ykz  ===> abc*123
+                //      %abc123  ===> *abc123
+                //      _abc123  ===> ?abc123
+                //      \\_abc1  ===> \\_abc1
+                //      abc\\_123 ===> abc\\_123
+                //      abc\\%123 ===> abc\\%123
+                // NOTE. user must input sql like 'abc\\_123' or 'abc\\%ykz'
+                for (int i = 0; i < chars.length; i++) {
+                    if (chars[i] == '_' || chars[i] == '%') {
+                        if (i == 0) {
+                            chars[i] = (chars[i] == '_') ? '?' : '*';
+                        } else if (chars[i - 1] != '\\') {
+                            chars[i] = (chars[i] == '_') ? '?' : '*';
+                        }
+                    }
+                }
+                return QueryBuilders.wildcardQuery(column, new String(chars));
+            } else {
+                return QueryBuilders.wildcardQuery(column, likePredicate.getChild(1).getStringValue());
+            }
+        }
+        if (expr instanceof InPredicate) {
+            InPredicate inPredicate = (InPredicate) expr;
+            List<Object> values = inPredicate.getListChildren().stream().map(EsUtil::extractDorisLiteral)
+                    .collect(Collectors.toList());
+            if (inPredicate.isNotIn()) {
+                return QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(column, values));
+            }
+            return QueryBuilders.termsQuery(column, values);
+        }
+        if (expr instanceof FunctionCallExpr) {
+            FunctionCallExpr functionCallExpr = (FunctionCallExpr) expr;
+            if ("esquery".equals(functionCallExpr.getFnName().getFunction())) {
+                String stringValue = functionCallExpr.getChild(1).getStringValue();
+                return new QueryBuilders.EsQueryBuilder(stringValue);
+            }
+        }
+        return null;
+    }
+
+    private static Object extractDorisLiteral(Expr expr) {
+        if (!expr.isLiteral()) {
+            return null;
+        }
+        if (expr instanceof BoolLiteral) {
+            BoolLiteral boolLiteral = (BoolLiteral) expr;
+            return boolLiteral.getValue();
+        } else if (expr instanceof DateLiteral) {
+            DateLiteral dateLiteral = (DateLiteral) expr;
+            return dateLiteral.getLongValue();
+        } else if (expr instanceof DecimalLiteral) {
+            DecimalLiteral decimalLiteral = (DecimalLiteral) expr;
+            return decimalLiteral.getValue();
+        } else if (expr instanceof FloatLiteral) {
+            FloatLiteral floatLiteral = (FloatLiteral) expr;
+            return floatLiteral.getValue();
+        } else if (expr instanceof IntLiteral) {
+            IntLiteral intLiteral = (IntLiteral) expr;
+            return intLiteral.getValue();
+        } else if (expr instanceof StringLiteral) {
+            StringLiteral stringLiteral = (StringLiteral) expr;
+            return stringLiteral.getStringValue();

Review Comment:
   We also need largeint literal



##########
fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java:
##########
@@ -87,12 +106,156 @@ public static JSONObject getJsonObject(JSONObject jsonObject, String key, int fr
         }
     }
 
+    /**
+     * Wrapper for get boolean value.
+     **/
     public static boolean getBoolean(Map<String, String> properties, String name) throws DdlException {
         String property = properties.get(name).trim();
         try {
             return Boolean.parseBoolean(property);
         } catch (Exception e) {
-            throw new DdlException(String.format("fail to parse %s, %s = %s, `%s` should be like 'true' or 'false', value should be double quotation marks", name, name, property, name));
+            throw new DdlException(String.format("fail to parse %s, %s = %s, `%s` should be like 'true' or 'false', "
+                    + "value should be double quotation marks", name, name, property, name));
+        }
+    }
+
+    /**
+     * Doris expr to es dsl.
+     **/
+    public static QueryBuilder convertToEsDsl(Expr expr) {
+        if (expr == null) {
+            return null;
+        }
+        // CompoundPredicate, `between` also converted to CompoundPredicate.
+        if (expr instanceof CompoundPredicate) {
+            CompoundPredicate compoundPredicate = (CompoundPredicate) expr;
+            switch (compoundPredicate.getOp()) {
+                case AND: {
+                    QueryBuilder left = convertToEsDsl(compoundPredicate.getChild(0));
+                    QueryBuilder right = convertToEsDsl(compoundPredicate.getChild(1));
+                    if (left != null && right != null) {
+                        return QueryBuilders.boolQuery().must(left).must(right);
+                    }
+                    return null;
+                }
+                case OR: {
+                    QueryBuilder left = convertToEsDsl(compoundPredicate.getChild(0));
+                    QueryBuilder right = convertToEsDsl(compoundPredicate.getChild(1));
+                    if (left != null && right != null) {
+                        return QueryBuilders.boolQuery().should(left).should(right);
+                    }
+                    return null;
+                }
+                case NOT: {
+                    QueryBuilder child = convertToEsDsl(compoundPredicate.getChild(0));
+                    if (child != null) {
+                        return QueryBuilders.boolQuery().mustNot(child);
+                    }
+                    return null;
+                }
+                default:
+                    return null;
+            }
+        }
+        TExprOpcode opCode = expr.getOpcode();
+        String column = ((SlotRef) expr.getChild(0)).getColumnName();
+        if (expr instanceof BinaryPredicate) {
+            Object value = extractDorisLiteral(expr.getChild(1));
+            switch (opCode) {
+                case EQ:
+                    return QueryBuilders.termQuery(column, value);
+                case NE:
+                    return QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(column, value));
+                case GE:
+                    return QueryBuilders.rangeQuery(column).gte(value);
+                case GT:
+                    return QueryBuilders.rangeQuery(column).gt(value);
+                case LE:
+                    return QueryBuilders.rangeQuery(column).lte(value);
+                case LT:
+                    return QueryBuilders.rangeQuery(column).lt(value);
+                case EQ_FOR_NULL:

Review Comment:
   move it up, like this
   ``` 
         case EQ:
         case EQ_FOR_NULL:
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org