[fix] Disable cast operation of object type (#8882)
Disable cast between string and object type(bitmap, hll, quantile_state)
This commit is contained in:
@ -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";
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user