[fix] Disable cast operation of object type (#8882)

Disable cast between string and object type(bitmap, hll, quantile_state)
This commit is contained in:
HappenLee
2022-04-08 09:13:56 +08:00
committed by GitHub
parent 69ab1f8681
commit fa8e4ec2f0
6 changed files with 48 additions and 43 deletions

View File

@ -134,23 +134,29 @@ public class CastExpr extends Expr {
return targetTypeDef;
}
private static boolean disableRegisterCastingFunction(Type fromType, Type toType) {
// Disable casting from boolean to decimal or datetime or date
if (fromType.isBoolean() &&
(toType.equals(Type.DECIMALV2) ||
toType.equals(Type.DATETIME) || toType.equals(Type.DATE))) {
return true;
}
// Disable casting operation of hll/bitmap/quantile_state
if (fromType.isObjectStored() || toType.isObjectStored()) {
return true;
}
// Disable no-op casting
return fromType.equals(toType);
}
public static void initBuiltins(FunctionSet functionSet) {
for (Type fromType : Type.getSupportedTypes()) {
if (fromType.isNull()) {
continue;
}
for (Type toType : Type.getSupportedTypes()) {
if (toType.isNull()) {
continue;
}
// Disable casting from boolean to decimal or datetime or date
if (fromType.isBoolean() &&
(toType.equals(Type.DECIMALV2) ||
toType.equals(Type.DATETIME) || toType.equals(Type.DATE))) {
continue;
}
// Disable no-op casts
if (fromType.equals(toType)) {
if (toType.isNull() || disableRegisterCastingFunction(fromType, toType)) {
continue;
}
String beClass = toType.isDecimalV2() || fromType.isDecimalV2() ? "DecimalV2Operators" : "CastFunctions";

View File

@ -89,8 +89,6 @@ public class FunctionCallExpr extends Expr {
private boolean isRewrote = false;
public static final String UNKNOWN_TABLE_FUNCTION_MSG = "This table function not supported now";
public void setIsAnalyticFnCall(boolean v) {
isAnalyticFnCall = v;
}
@ -827,7 +825,7 @@ public class FunctionCallExpr extends Expr {
fn = getTableFunction(fnName.getFunction(), childTypes,
Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
if (fn == null) {
throw new AnalysisException(UNKNOWN_TABLE_FUNCTION_MSG);
throw new AnalysisException(getFunctionNotFoundError(argTypes));
}
} else {
// now first find function in built-in functions

View File

@ -248,9 +248,6 @@ public enum PrimitiveType {
builder.put(VARCHAR, DECIMALV2);
builder.put(VARCHAR, VARCHAR);
builder.put(VARCHAR, STRING);
builder.put(VARCHAR, HLL);
builder.put(VARCHAR, BITMAP);
builder.put(VARCHAR, QUANTILE_STATE);
// Varchar
builder.put(STRING, BOOLEAN);
@ -266,9 +263,6 @@ public enum PrimitiveType {
builder.put(STRING, DECIMALV2);
builder.put(STRING, VARCHAR);
builder.put(STRING, STRING);
builder.put(STRING, HLL);
builder.put(STRING, BITMAP);
builder.put(STRING, QUANTILE_STATE);
// DecimalV2
builder.put(DECIMALV2, BOOLEAN);
@ -285,18 +279,12 @@ public enum PrimitiveType {
// HLL
builder.put(HLL, HLL);
builder.put(HLL, VARCHAR);
builder.put(HLL, STRING);
// BITMAP
builder.put(BITMAP, BITMAP);
builder.put(BITMAP, VARCHAR);
builder.put(BITMAP, STRING);
// QUANTILE_STATE
builder.put(QUANTILE_STATE, QUANTILE_STATE);
builder.put(QUANTILE_STATE, VARCHAR);
builder.put(QUANTILE_STATE, STRING);
//TIME
builder.put(TIME, TIME);

View File

@ -546,9 +546,6 @@ public class ScalarType extends Type {
if (type == PrimitiveType.VARCHAR && scalarType.isStringType()) {
return true;
}
if (type == PrimitiveType.HLL && scalarType.isStringType()) {
return true;
}
if (isDecimalV2() && scalarType.isWildcardDecimal()) {
Preconditions.checkState(!isWildcardDecimal());
return true;
@ -682,6 +679,15 @@ public class ScalarType extends Type {
return INVALID;
}
boolean t1IsBitMap = t1.type == PrimitiveType.BITMAP;
boolean t2IsBitMap = t2.type == PrimitiveType.BITMAP;
if (t1IsBitMap || t2IsBitMap) {
if (t1IsBitMap && t2IsBitMap) {
return BITMAP;
}
return INVALID;
}
// for cast all type
if (t1.type == PrimitiveType.ALL || t2.type == PrimitiveType.ALL) {
return Type.ALL;

View File

@ -476,18 +476,6 @@ public class QueryPlanTest {
Assert.assertTrue(explainString.contains("OUTPUT EXPRS:`id` | `id2`"));
Assert.assertTrue(explainString.contains("0:OlapScanNode"));
queryStr = "explain insert into test.bitmap_table select id, to_bitmap(id2) from test.bitmap_table_2;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, queryStr);
Assert.assertTrue(explainString.contains("OLAP TABLE SINK"));
Assert.assertTrue(explainString.contains("OUTPUT EXPRS:`id` | to_bitmap(CAST(`id2` AS CHARACTER))"));
Assert.assertTrue(explainString.contains("0:OlapScanNode"));
queryStr = "explain insert into test.bitmap_table select id, bitmap_hash(id2) from test.bitmap_table_2;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, queryStr);
Assert.assertTrue(explainString.contains("OLAP TABLE SINK"));
Assert.assertTrue(explainString.contains("OUTPUT EXPRS:`id` | bitmap_hash(CAST(`id2` AS CHARACTER))"));
Assert.assertTrue(explainString.contains("0:OlapScanNode"));
queryStr = "explain insert into test.bitmap_table select id, id from test.bitmap_table_2;";
String errorMsg = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, queryStr);
Assert.assertTrue(errorMsg.contains("bitmap column require the function return type is BITMAP"));
@ -615,6 +603,25 @@ public class QueryPlanTest {
sql = "SHOW VARIABLES LIKE 'lower_case_%'; SHOW VARIABLES LIKE 'sql_mode'";
List<StatementBase> stmts = UtFrameUtils.parseAndAnalyzeStmts(sql, connectContext);
Assert.assertEquals(2, stmts.size());
// disable cast hll/bitmap to string
testHLLQueryPlan(
"select cast(id2 as varchar) from test.hll_table;",
"Invalid type cast of `id2` from HLL to VARCHAR(*)"
);
testBitmapQueryPlan(
"select cast(id2 as varchar) from test.bitmap_table;",
"Invalid type cast of `id2` from BITMAP to VARCHAR(*)"
);
// disable implicit cast hll/bitmap to string
testHLLQueryPlan(
"select length(id2) from test.hll_table;",
"No matching function with signature: length(hll)"
);
testBitmapQueryPlan(
"select length(id2) from test.bitmap_table;",
"No matching function with signature: length(bitmap)"
);
}
@Test

View File

@ -184,11 +184,11 @@ public class TableFunctionPlanTest {
public void errorParam() throws Exception {
String sql = "explain select k1, e1 from db1.tbl1 lateral view explode_split(k2) tmp as e1;";
String explainString = UtFrameUtils.getSQLPlanOrErrorMsg(ctx, sql);
Assert.assertTrue(explainString.contains(FunctionCallExpr.UNKNOWN_TABLE_FUNCTION_MSG));
Assert.assertTrue(explainString.contains("No matching function with signature: explode_split(varchar(1))"));
sql = "explain select k1, e1 from db1.tbl1 lateral view explode_split(k1) tmp as e1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(ctx, sql);
Assert.assertTrue(explainString.contains(FunctionCallExpr.UNKNOWN_TABLE_FUNCTION_MSG));
Assert.assertTrue(explainString.contains("No matching function with signature: explode_split(int(11))"));
}
/* Case2 table function in where stmt