From 3c784b9c90770d5095fe710d295f00f3feb69a25 Mon Sep 17 00:00:00 2001 From: "xueyan.li" Date: Thu, 27 Aug 2020 12:15:28 +0800 Subject: [PATCH] [SQL] support StringLiteral try to cast BigInt (#4445) --- .../doris/analysis/BinaryPredicate.java | 22 ++++++++++++ .../java/org/apache/doris/catalog/Type.java | 12 +++++++ .../apache/doris/analysis/SelectStmtTest.java | 36 ++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java index ad2457124d..38068ce793 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java @@ -307,6 +307,28 @@ public class BinaryPredicate extends Predicate implements Writable { return Type.LARGEINT; } + // Implicit conversion affects query performance. + // For a common example datekey='20200825' which datekey is int type. + // If we up conversion to double type directly. + // PartitionPruner will not take effect. Then it will scan all partitions. + // When int column compares with string, Mysql will convert string to int. + // So it is also compatible with Mysql. + + if (t1 == PrimitiveType.BIGINT && t2 == PrimitiveType.VARCHAR) { + Expr rightChild = getChild(1); + Long parsedLong = Type.tryParseToLong(rightChild); + if(parsedLong != null) { + return Type.BIGINT; + } + } + if (t1 == PrimitiveType.VARCHAR && t2 == PrimitiveType.BIGINT) { + Expr leftChild = getChild(0); + Long parsedLong = Type.tryParseToLong(leftChild); + if(parsedLong != null) { + return Type.BIGINT; + } + } + return Type.DOUBLE; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java index 4ba15c133c..ada2e2bd93 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java @@ -386,6 +386,18 @@ public abstract class Type { return ScalarType.INVALID; } + /** + * Returns null if this expr is not instance of StringLiteral or StringLiteral + * inner value could not parse to long. otherwise return parsed Long result. + */ + public static Long tryParseToLong(Expr expectStringExpr){ + if (expectStringExpr instanceof StringLiteral) { + String value = ((StringLiteral)expectStringExpr).getValue(); + return Longs.tryParse(value); + } + return null; + } + /** * Returns true if this type exceeds the MAX_NESTING_DEPTH, false otherwise. */ diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java index e03e8c5a39..278e69d64e 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java @@ -50,9 +50,25 @@ public class SelectStmtTest { + "AGGREGATE KEY(k1, k2,k3,k4) distributed by hash(k1) buckets 3 properties('replication_num' = '1');"; String createBaseAllStmtStr = "create table db1.baseall(k1 int, k2 varchar(32)) distributed by hash(k1) " + "buckets 3 properties('replication_num' = '1');"; + String createPratitionTableStr = "CREATE TABLE db1.partition_table (\n" + + "datekey int(11) NULL COMMENT \"datekey\",\n" + + "poi_id bigint(20) NULL COMMENT \"poi_id\"\n" + + ") ENGINE=OLAP\n" + + "AGGREGATE KEY(datekey, poi_id)\n" + + "COMMENT \"OLAP\"\n" + + "PARTITION BY RANGE(datekey)\n" + + "(PARTITION p20200727 VALUES [(\"20200726\"), (\"20200727\")),\n" + + "PARTITION p20200728 VALUES [(\"20200727\"), (\"20200728\")))\n" + + "DISTRIBUTED BY HASH(poi_id) BUCKETS 2\n" + + "PROPERTIES (\n" + + "\"storage_type\" = \"COLUMN\",\n" + + "\"replication_num\" = \"1\"\n" + + ");"; dorisAssert = new DorisAssert(); dorisAssert.withDatabase("db1").useDatabase("db1"); - dorisAssert.withTable(createTblStmtStr).withTable(createBaseAllStmtStr); + dorisAssert.withTable(createTblStmtStr) + .withTable(createBaseAllStmtStr) + .withTable(createPratitionTableStr); } @Test @@ -362,4 +378,22 @@ public class SelectStmtTest { "from information_schema.collations"; dorisAssert.query(sql).explainQuery(); } + + @Test + public void testVarcharToLongSupport() throws Exception { + String sql = "select count(*)\n" + + "from db1.partition_table\n" + + "where datekey='20200730'"; + Assert.assertTrue(dorisAssert + .query(sql) + .explainQuery() + .contains("`datekey` = 20200730")); + sql = "select count(*)\n" + + "from db1.partition_table\n" + + "where '20200730'=datekey"; + Assert.assertTrue(dorisAssert + .query(sql) + .explainQuery() + .contains("`datekey` = 20200730")); + } }