This is an automated email from the ASF dual-hosted git repository.

panxiaolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e9223f6a19 [Feature](aggregation) add agg_state define and ddl support 
(#19824)
e9223f6a19 is described below

commit e9223f6a19a255d504d3a61a5c1a1aebf0d03b19
Author: Pxl <[email protected]>
AuthorDate: Mon May 22 11:45:53 2023 +0800

    [Feature](aggregation) add agg_state define and ddl support (#19824)
    
    add agg_state define and ddl support
---
 .../org/apache/doris/catalog/PrimitiveType.java    |  12 ++-
 .../java/org/apache/doris/catalog/ScalarType.java  |  82 ++++++++++++++--
 .../main/java/org/apache/doris/catalog/Type.java   |  44 ++++++++-
 fe/fe-core/src/main/cup/sql_parser.cup             |  47 ++++++++--
 .../java/org/apache/doris/analysis/ColumnDef.java  |  48 +++++++++-
 .../apache/doris/analysis/CreateFunctionStmt.java  |   3 +
 .../org/apache/doris/analysis/DescribeStmt.java    |   7 +-
 .../org/apache/doris/analysis/SlotDescriptor.java  |   2 +-
 .../java/org/apache/doris/analysis/TypeDef.java    |  10 ++
 .../org/apache/doris/catalog/AggregateType.java    |   8 +-
 .../main/java/org/apache/doris/catalog/Column.java |  51 +++++++++-
 .../doris/catalog/external/HMSExternalTable.java   |   5 +-
 .../doris/common/proc/IndexSchemaProcNode.java     |   7 +-
 .../java/org/apache/doris/common/util/Util.java    |   1 +
 .../expressions/functions/agg/IntersectCount.java  |   2 +-
 .../apache/doris/nereids/types/AggStateType.java   | 103 +++++++++++++++++++++
 .../org/apache/doris/nereids/types/DataType.java   |  16 ++++
 .../org/apache/doris/nereids/types/HllType.java    |   2 +-
 .../doris/nereids/types/QuantileStateType.java     |   2 +-
 .../doris/nereids/util/TypeCoercionUtils.java      |   2 +-
 fe/fe-core/src/main/jflex/sql_scanner.flex         |   1 +
 .../doris/planner/TableFunctionPlanTest.java       |  34 +++----
 .../data/types/test_show_data_types.out            |   1 +
 .../suites/nereids_syntax_p0/explain.groovy        |   2 +-
 24 files changed, 434 insertions(+), 58 deletions(-)

diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/catalog/PrimitiveType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/PrimitiveType.java
index 0ab70f4275..a7d2475630 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/PrimitiveType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/PrimitiveType.java
@@ -59,6 +59,7 @@ public enum PrimitiveType {
     HLL("HLL", 16, TPrimitiveType.HLL, true),
     BITMAP("BITMAP", 16, TPrimitiveType.OBJECT, true),
     QUANTILE_STATE("QUANTILE_STATE", 16, TPrimitiveType.QUANTILE_STATE, true),
+    AGG_STATE("AGG_STATE", 16, TPrimitiveType.AGG_STATE, true),
     DATEV2("DATEV2", 4, TPrimitiveType.DATEV2, true),
     DATETIMEV2("DATETIMEV2", 8, TPrimitiveType.DATETIMEV2, true),
     TIMEV2("TIMEV2", 8, TPrimitiveType.TIMEV2, false),
@@ -493,6 +494,9 @@ public enum PrimitiveType {
         // QUANTILE_STATE
         builder.put(QUANTILE_STATE, QUANTILE_STATE);
 
+        builder.put(AGG_STATE, AGG_STATE);
+        builder.put(AGG_STATE, VARCHAR);
+
         // TIME
         builder.put(TIME, TIME);
         builder.put(TIME, TIMEV2);
@@ -561,6 +565,7 @@ public enum PrimitiveType {
         supportedTypes.add(MAP);
         supportedTypes.add(QUANTILE_STATE);
         supportedTypes.add(VARIANT);
+        supportedTypes.add(AGG_STATE);
     }
 
     public static ArrayList<PrimitiveType> getIntegerTypes() {
@@ -624,6 +629,7 @@ public enum PrimitiveType {
         compatibilityMatrix[NULL_TYPE.ordinal()][TIMEV2.ordinal()] = TIMEV2;
         compatibilityMatrix[NULL_TYPE.ordinal()][BITMAP.ordinal()] = BITMAP;
         compatibilityMatrix[NULL_TYPE.ordinal()][QUANTILE_STATE.ordinal()] = 
QUANTILE_STATE;
+        compatibilityMatrix[NULL_TYPE.ordinal()][AGG_STATE.ordinal()] = 
AGG_STATE;
 
         compatibilityMatrix[BOOLEAN.ordinal()][BOOLEAN.ordinal()] = BOOLEAN;
         compatibilityMatrix[BOOLEAN.ordinal()][TINYINT.ordinal()] = TINYINT;
@@ -911,6 +917,8 @@ public enum PrimitiveType {
         compatibilityMatrix[TIMEV2.ordinal()][TIMEV2.ordinal()] = TIMEV2;
 
         
compatibilityMatrix[QUANTILE_STATE.ordinal()][QUANTILE_STATE.ordinal()] = 
QUANTILE_STATE;
+
+        compatibilityMatrix[AGG_STATE.ordinal()][AGG_STATE.ordinal()] = 
INVALID_TYPE;
     }
 
     static {
@@ -1002,6 +1010,8 @@ public enum PrimitiveType {
                 return BITMAP;
             case QUANTILE_STATE:
                 return QUANTILE_STATE;
+            case AGG_STATE:
+                return AGG_STATE;
             case ARRAY:
                 return ARRAY;
             case MAP:
@@ -1141,7 +1151,7 @@ public enum PrimitiveType {
     }
 
     public boolean isStringType() {
-        return (this == VARCHAR || this == CHAR || this == HLL || this == 
STRING);
+        return (this == VARCHAR || this == CHAR || this == STRING || this == 
AGG_STATE);
     }
 
     public boolean isJsonbType() {
diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java
index e4dd45f17b..d3d40642aa 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java
@@ -30,6 +30,8 @@ import com.google.gson.annotations.SerializedName;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -122,10 +124,30 @@ public class ScalarType extends Type {
     @SerializedName(value = "lenStr")
     private String lenStr;
 
+    @SerializedName(value = "subTypes")
+    private List<Type> subTypes;
+
+    @SerializedName(value = "subTypeNullables")
+    private List<Boolean> subTypeNullables;
+
+    public List<Type> getSubTypes() {
+        return subTypes;
+    }
+
+    public List<Boolean> getSubTypeNullables() {
+        return subTypeNullables;
+    }
+
     public ScalarType(PrimitiveType type) {
         this.type = type;
     }
 
+    public ScalarType(List<Type> subTypes, List<Boolean> subTypeNullables) {
+        this.type = PrimitiveType.AGG_STATE;
+        this.subTypes = subTypes;
+        this.subTypeNullables = subTypeNullables;
+    }
+
     public static ScalarType createType(PrimitiveType type, int len, int 
precision, int scale) {
         switch (type) {
             case CHAR:
@@ -183,6 +205,8 @@ public class ScalarType extends Type {
                 return BITMAP;
             case QUANTILE_STATE:
                 return QUANTILE_STATE;
+            case AGG_STATE:
+                return AGG_STATE;
             case LAMBDA_FUNCTION:
                 return LAMBDA_FUNCTION;
             case DATE:
@@ -251,6 +275,8 @@ public class ScalarType extends Type {
                 return BITMAP;
             case "QUANTILE_STATE":
                 return QUANTILE_STATE;
+            case "AGG_STATE":
+                return AGG_STATE;
             case "LAMBDA_FUNCTION":
                 return LAMBDA_FUNCTION;
             case "DATE":
@@ -565,7 +591,9 @@ public class ScalarType extends Type {
                 }
                 break;
             case VARCHAR:
-                if (Strings.isNullOrEmpty(lenStr)) {
+                if (isWildcardVarchar()) {
+                    stringBuilder.append("varchar(*)");
+                } else if (Strings.isNullOrEmpty(lenStr)) {
                     
stringBuilder.append("varchar").append("(").append(len).append(")");
                 } else {
                     
stringBuilder.append("varchar").append("(`").append(lenStr).append("`)");
@@ -627,6 +655,8 @@ public class ScalarType extends Type {
             case VARIANT:
             case QUANTILE_STATE:
             case LAMBDA_FUNCTION:
+            case ARRAY:
+            case NULL_TYPE:
                 stringBuilder.append(type.toString().toLowerCase());
                 break;
             case STRING:
@@ -635,11 +665,18 @@ public class ScalarType extends Type {
             case JSONB:
                 stringBuilder.append("json");
                 break;
-            case ARRAY:
-                stringBuilder.append(type.toString().toLowerCase());
-                break;
-            case NULL_TYPE:
-                stringBuilder.append(type.toString().toLowerCase());
+            case AGG_STATE:
+                stringBuilder.append("agg_state(");
+                for (int i = 0; i < subTypes.size(); i++) {
+                    if (i > 0) {
+                        stringBuilder.append(", ");
+                    }
+                    stringBuilder.append(subTypes.get(i).toSql());
+                    if (subTypeNullables.get(i)) {
+                        stringBuilder.append(" NULL");
+                    }
+                }
+                stringBuilder.append(")");
                 break;
             default:
                 stringBuilder.append("unknown type: " + type.toString());
@@ -685,6 +722,18 @@ public class ScalarType extends Type {
                 break;
         }
         node.setScalarType(scalarType);
+
+        if (subTypes != null) {
+            List<TTypeDesc> types = new ArrayList<TTypeDesc>();
+            for (int i = 0; i < subTypes.size(); i++) {
+                TTypeDesc desc = new TTypeDesc();
+                desc.setTypes(new ArrayList<TTypeNode>());
+                subTypes.get(i).toThrift(desc);
+                desc.setIsNullable(subTypeNullables.get(i));
+                types.add(desc);
+            }
+            container.setSubTypes(types);
+        }
     }
 
     public int decimalPrecision() {
@@ -829,10 +878,7 @@ public class ScalarType extends Type {
             Preconditions.checkState(!isWildcardChar());
             return true;
         }
-        if (type == PrimitiveType.CHAR && scalarType.isStringType()) {
-            return true;
-        }
-        if (type == PrimitiveType.VARCHAR && scalarType.isStringType()) {
+        if (type.isStringType() && scalarType.isStringType()) {
             return true;
         }
         if (isDecimalV2() && scalarType.isWildcardDecimal() && 
scalarType.isDecimalV2()) {
@@ -861,6 +907,22 @@ public class ScalarType extends Type {
             return false;
         }
         ScalarType other = (ScalarType) o;
+        if (this.isAggStateType() && other.isAggStateType()) {
+            int subTypeNumber = subTypeNullables.size();
+            if (subTypeNumber != other.subTypeNullables.size()) {
+                return false;
+            }
+            for (int i = 0; i < subTypeNumber; i++) {
+                if 
(!subTypeNullables.get(i).equals(other.subTypeNullables.get(i))) {
+                    return false;
+                }
+                if (!subTypes.get(i).equals(other.subTypes.get(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
         if ((this.isDatetimeV2() && other.isDatetimeV2()) || (this.isTimeV2() 
&& other.isTimeV2())) {
             return this.decimalScale() == other.decimalScale();
         }
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index 48228a6c06..c1bcc9c9ae 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -102,6 +102,7 @@ public abstract class Type {
     public static final ScalarType CHAR = ScalarType.createCharType(-1);
     public static final ScalarType BITMAP = new 
ScalarType(PrimitiveType.BITMAP);
     public static final ScalarType QUANTILE_STATE = new 
ScalarType(PrimitiveType.QUANTILE_STATE);
+    public static final ScalarType AGG_STATE = new 
ScalarType(PrimitiveType.AGG_STATE);
     public static final ScalarType LAMBDA_FUNCTION = new 
ScalarType(PrimitiveType.LAMBDA_FUNCTION);
     // Only used for alias function, to represent any type in function args
     public static final ScalarType ALL = new ScalarType(PrimitiveType.ALL);
@@ -175,6 +176,7 @@ public abstract class Type {
         supportedTypes.add(HLL);
         supportedTypes.add(BITMAP);
         supportedTypes.add(QUANTILE_STATE);
+        supportedTypes.add(AGG_STATE);
 
         arraySubTypes = Lists.newArrayList();
         arraySubTypes.add(BOOLEAN);
@@ -417,7 +419,7 @@ public abstract class Type {
     public boolean isStringType() {
         return isScalarType(PrimitiveType.VARCHAR)
                 || isScalarType(PrimitiveType.CHAR)
-                || isScalarType(PrimitiveType.STRING);
+                || isScalarType(PrimitiveType.STRING) || 
isScalarType(PrimitiveType.AGG_STATE);
     }
 
     public boolean isVarcharOrStringType() {
@@ -554,6 +556,10 @@ public abstract class Type {
         return this instanceof ArrayType;
     }
 
+    public boolean isAggStateType() {
+        return isScalarType(PrimitiveType.AGG_STATE);
+    }
+
     public boolean isMultiRowType() {
         return this instanceof MultiRowType;
     }
@@ -889,6 +895,8 @@ public abstract class Type {
                 return new VariantType();
             case LAMBDA_FUNCTION:
                 return Type.LAMBDA_FUNCTION;
+            case AGG_STATE:
+                return Type.AGG_STATE;
             default:
                 return null;
         }
@@ -1244,6 +1252,7 @@ public abstract class Type {
         compatibilityMatrix[BOOLEAN.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BOOLEAN.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BOOLEAN.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[BOOLEAN.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // TINYINT
         compatibilityMatrix[TINYINT.ordinal()][SMALLINT.ordinal()] = 
PrimitiveType.SMALLINT;
@@ -1270,6 +1279,7 @@ public abstract class Type {
         compatibilityMatrix[TINYINT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TINYINT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TINYINT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[TINYINT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // SMALLINT
         compatibilityMatrix[SMALLINT.ordinal()][INT.ordinal()] = 
PrimitiveType.INT;
@@ -1295,6 +1305,7 @@ public abstract class Type {
         compatibilityMatrix[SMALLINT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[SMALLINT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[SMALLINT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[SMALLINT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // INT
         compatibilityMatrix[INT.ordinal()][BIGINT.ordinal()] = 
PrimitiveType.BIGINT;
@@ -1323,6 +1334,7 @@ public abstract class Type {
         compatibilityMatrix[INT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[INT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[INT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[INT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // BIGINT
         // 64 bit integer does not fit in mantissa of double or float.
@@ -1352,6 +1364,7 @@ public abstract class Type {
         compatibilityMatrix[BIGINT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BIGINT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BIGINT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[BIGINT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // LARGEINT
         compatibilityMatrix[LARGEINT.ordinal()][FLOAT.ordinal()] = 
PrimitiveType.DOUBLE;
@@ -1373,6 +1386,7 @@ public abstract class Type {
         compatibilityMatrix[LARGEINT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[LARGEINT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[LARGEINT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[LARGEINT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // FLOAT
         compatibilityMatrix[FLOAT.ordinal()][DOUBLE.ordinal()] = 
PrimitiveType.DOUBLE;
@@ -1393,6 +1407,7 @@ public abstract class Type {
         compatibilityMatrix[FLOAT.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[FLOAT.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[FLOAT.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[FLOAT.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DOUBLE
         compatibilityMatrix[DOUBLE.ordinal()][DATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1412,6 +1427,7 @@ public abstract class Type {
         compatibilityMatrix[DOUBLE.ordinal()][DATEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DOUBLE.ordinal()][DATETIMEV2.ordinal()] = 
PrimitiveType.DOUBLE;
         compatibilityMatrix[DOUBLE.ordinal()][TIMEV2.ordinal()] = 
PrimitiveType.DOUBLE;
+        compatibilityMatrix[DOUBLE.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DATE
         compatibilityMatrix[DATE.ordinal()][DATETIME.ordinal()] = 
PrimitiveType.DATETIME;
@@ -1430,6 +1446,7 @@ public abstract class Type {
         compatibilityMatrix[DATE.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATE.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATE.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[DATE.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DATEV2
         compatibilityMatrix[DATEV2.ordinal()][DATE.ordinal()] = 
PrimitiveType.DATEV2;
@@ -1448,6 +1465,7 @@ public abstract class Type {
         compatibilityMatrix[DATEV2.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATEV2.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATEV2.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[DATEV2.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DATETIME
         compatibilityMatrix[DATETIME.ordinal()][CHAR.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1465,6 +1483,7 @@ public abstract class Type {
         compatibilityMatrix[DATETIME.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATETIME.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATETIME.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[DATETIME.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DATETIMEV2
         compatibilityMatrix[DATETIMEV2.ordinal()][CHAR.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1482,6 +1501,7 @@ public abstract class Type {
         compatibilityMatrix[DATETIMEV2.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATETIMEV2.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DATETIMEV2.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[DATETIMEV2.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // We can convert some but not all string values to timestamps.
         // CHAR
@@ -1499,6 +1519,7 @@ public abstract class Type {
         compatibilityMatrix[CHAR.ordinal()][STRING.ordinal()] = 
PrimitiveType.STRING;
         compatibilityMatrix[CHAR.ordinal()][JSONB.ordinal()] = 
PrimitiveType.CHAR;
         compatibilityMatrix[CHAR.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[CHAR.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // VARCHAR
         compatibilityMatrix[VARCHAR.ordinal()][DECIMALV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1514,6 +1535,7 @@ public abstract class Type {
         compatibilityMatrix[VARCHAR.ordinal()][STRING.ordinal()] = 
PrimitiveType.STRING;
         compatibilityMatrix[VARCHAR.ordinal()][JSONB.ordinal()] = 
PrimitiveType.VARCHAR;
         compatibilityMatrix[VARCHAR.ordinal()][QUANTILE_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[VARCHAR.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         //String
         compatibilityMatrix[STRING.ordinal()][HLL.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1527,6 +1549,7 @@ public abstract class Type {
         compatibilityMatrix[STRING.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[STRING.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[STRING.ordinal()][JSONB.ordinal()] = 
PrimitiveType.STRING;
+        compatibilityMatrix[STRING.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         //JSONB
         compatibilityMatrix[JSONB.ordinal()][DECIMALV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1543,6 +1566,7 @@ public abstract class Type {
         compatibilityMatrix[JSONB.ordinal()][STRING.ordinal()] = 
PrimitiveType.STRING;
         compatibilityMatrix[JSONB.ordinal()][CHAR.ordinal()] = 
PrimitiveType.CHAR;
         compatibilityMatrix[JSONB.ordinal()][VARCHAR.ordinal()] = 
PrimitiveType.VARCHAR;
+        compatibilityMatrix[JSONB.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DECIMALV2
         compatibilityMatrix[DECIMALV2.ordinal()][HLL.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1557,6 +1581,7 @@ public abstract class Type {
         compatibilityMatrix[DECIMALV2.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DECIMALV2.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DECIMALV2.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[DECIMALV2.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DECIMAL32
         compatibilityMatrix[DECIMAL32.ordinal()][HLL.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1570,6 +1595,7 @@ public abstract class Type {
         compatibilityMatrix[DECIMAL32.ordinal()][DECIMALV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.DECIMAL64;
         compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.DECIMAL128;
+        compatibilityMatrix[DECIMAL32.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DECIMAL64
         compatibilityMatrix[DECIMAL64.ordinal()][HLL.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1583,6 +1609,7 @@ public abstract class Type {
         compatibilityMatrix[DECIMAL64.ordinal()][DECIMALV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.DECIMAL64;
         compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.DECIMAL128;
+        compatibilityMatrix[DECIMAL64.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // DECIMAL128
         compatibilityMatrix[DECIMAL128.ordinal()][HLL.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1596,6 +1623,7 @@ public abstract class Type {
         compatibilityMatrix[DECIMAL128.ordinal()][DECIMALV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[DECIMAL128.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.DECIMAL128;
         compatibilityMatrix[DECIMAL128.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.DECIMAL128;
+        compatibilityMatrix[DECIMAL128.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // HLL
         compatibilityMatrix[HLL.ordinal()][TIME.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1609,6 +1637,7 @@ public abstract class Type {
         compatibilityMatrix[HLL.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[HLL.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[HLL.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[HLL.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
 
         // BITMAP
@@ -1622,6 +1651,7 @@ public abstract class Type {
         compatibilityMatrix[BITMAP.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BITMAP.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[BITMAP.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[BITMAP.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         //QUANTILE_STATE
         compatibilityMatrix[QUANTILE_STATE.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1631,6 +1661,16 @@ public abstract class Type {
         compatibilityMatrix[QUANTILE_STATE.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[QUANTILE_STATE.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[QUANTILE_STATE.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[QUANTILE_STATE.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+
+        //AGG_STATE
+        compatibilityMatrix[AGG_STATE.ordinal()][JSONB.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][STRING.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][DATEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][DATETIMEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[AGG_STATE.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // TIME why here not???
         compatibilityMatrix[TIME.ordinal()][TIME.ordinal()] = 
PrimitiveType.INVALID_TYPE;
@@ -1640,12 +1680,14 @@ public abstract class Type {
         compatibilityMatrix[TIME.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIME.ordinal()][DATEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIME.ordinal()][DATETIMEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[TIME.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         compatibilityMatrix[TIMEV2.ordinal()][TIMEV2.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIMEV2.ordinal()][TIME.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIMEV2.ordinal()][DECIMAL32.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIMEV2.ordinal()][DECIMAL64.ordinal()] = 
PrimitiveType.INVALID_TYPE;
         compatibilityMatrix[TIMEV2.ordinal()][DECIMAL128.ordinal()] = 
PrimitiveType.INVALID_TYPE;
+        compatibilityMatrix[TIMEV2.ordinal()][AGG_STATE.ordinal()] = 
PrimitiveType.INVALID_TYPE;
 
         // Check all of the necessary entries that should be filled.
         // ignore binary and all
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup 
b/fe/fe-core/src/main/cup/sql_parser.cup
index 8d7a45c36b..605e92e448 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -512,6 +512,7 @@ terminal String
     KW_PROPERTY,
     KW_QUANTILE_STATE,
     KW_QUANTILE_UNION,
+    KW_AGG_STATE,
     KW_QUERY,
     KW_QUOTA,
     KW_RANDOM,
@@ -740,8 +741,8 @@ nonterminal OrderByElement order_by_element;
 nonterminal Boolean opt_order_param;
 nonterminal Boolean opt_nulls_order_param;
 nonterminal LimitElement limit_clause;
-nonterminal TypeDef type_def, opt_intermediate_type;
-nonterminal List<TypeDef> type_def_list;
+nonterminal TypeDef type_def, type_def_nullable, opt_intermediate_type;
+nonterminal List<TypeDef> type_def_list, type_def_nullable_list;
 nonterminal FunctionArgsDef func_args_def;
 nonterminal Type type;
 nonterminal Expr cast_expr, case_else_clause, analytic_expr;
@@ -3014,9 +3015,7 @@ recover_stmt ::=
     ;
 
 opt_agg_type ::=
-    /* not set */
-    {: RESULT = null; :}
-    | KW_SUM
+    KW_SUM
     {:
     RESULT = AggregateType.SUM;
     :}
@@ -3044,8 +3043,6 @@ opt_agg_type ::=
     {:
     RESULT = AggregateType.BITMAP_UNION;
     :}
-
-
     | KW_QUANTILE_UNION
     {:
     RESULT = AggregateType.QUANTILE_UNION;
@@ -3443,7 +3440,19 @@ opt_is_key ::=
     ;
 
 column_definition ::=
-    ident:columnName type_def:typeDef opt_is_key:isKey opt_agg_type:aggType 
opt_is_allow_null:isAllowNull opt_default_value:defaultValue opt_comment:comment
+    ident:columnName type_def:typeDef opt_is_key:isKey 
opt_is_allow_null:isAllowNull opt_default_value:defaultValue opt_comment:comment
+    {:
+        ColumnDef columnDef = new ColumnDef(columnName, typeDef, isKey, null, 
isAllowNull, defaultValue, comment);
+        RESULT = columnDef;
+    :}
+    | ident:columnName type_def:typeDef IDENT:fnName LPAREN 
type_def_nullable_list:list RPAREN opt_default_value:defaultValue 
opt_comment:comment
+    {:
+        ColumnDef columnDef = new ColumnDef(columnName, typeDef, false, 
AggregateType.GENERIC_AGGREGATION, false, defaultValue, comment);
+        columnDef.setGenericAggregationName(fnName);
+        columnDef.setGenericAggregationArguments(list);
+        RESULT = columnDef;
+    :}
+    | ident:columnName type_def:typeDef opt_is_key:isKey opt_agg_type:aggType 
opt_is_allow_null:isAllowNull opt_default_value:defaultValue opt_comment:comment
     {:
         ColumnDef columnDef = new ColumnDef(columnName, typeDef, isKey, 
aggType, isAllowNull, defaultValue, comment);
         RESULT = columnDef;
@@ -5994,6 +6003,8 @@ type ::=
   {: RESULT = Type.BITMAP; :}
   | KW_QUANTILE_STATE
   {: RESULT = Type.QUANTILE_STATE; :}
+  | KW_AGG_STATE
+  {: RESULT = Type.AGG_STATE; :}
   | KW_STRING
   {: RESULT = ScalarType.createStringType(); :}
   | KW_JSON
@@ -6089,6 +6100,24 @@ type_def_list ::=
   :}
   ;
 
+type_def_nullable ::=
+  type:t opt_is_allow_null:isAllowNull
+  {: RESULT = new TypeDef(t, isAllowNull); :}
+  ;
+
+type_def_nullable_list ::=
+  type_def_nullable:typeDef
+  {:
+    RESULT = Lists.newArrayList(typeDef);
+  :}
+  | type_def_nullable_list:types COMMA type_def_nullable:typeDef
+  {:
+    types.add(typeDef);
+    RESULT = types;
+  :}
+  ;
+
+
 func_args_def ::=
   type_def_list:argTypes
   {:
@@ -7071,6 +7100,8 @@ keyword ::=
     {: RESULT = id; :}
     | KW_QUANTILE_STATE:id
     {: RESULT = id; :}
+    | KW_AGG_STATE:id
+    {: RESULT = id; :}
     | KW_BITMAP_UNION:id
     {: RESULT = id; :}
     | KW_NGRAM_BF:id
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
index 3500f1bb97..3e1baef1c6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
@@ -35,6 +35,8 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
 
 // Column definition which is generated by SQL syntax parser
 // Syntax:
@@ -116,6 +118,9 @@ public class ColumnDef {
     private String name;
     private TypeDef typeDef;
     private AggregateType aggregateType;
+    private String genericAggregationName;
+    private List<TypeDef> genericAggregationArguments;
+
     private boolean isKey;
     private boolean isAllowNull;
     private DefaultValue defaultValue;
@@ -203,6 +208,14 @@ public class ColumnDef {
         this.aggregateType = aggregateType;
     }
 
+    public void setGenericAggregationName(String genericAggregationName) {
+        this.genericAggregationName = genericAggregationName;
+    }
+
+    public void setGenericAggregationArguments(List<TypeDef> 
genericAggregationArguments) {
+        this.genericAggregationArguments = genericAggregationArguments;
+    }
+
     public boolean isKey() {
         return isKey;
     }
@@ -274,7 +287,8 @@ public class ColumnDef {
             }
 
             // check if aggregate type is valid
-            if (!aggregateType.checkCompatibility(type.getPrimitiveType())) {
+            if (aggregateType != AggregateType.GENERIC_AGGREGATION
+                    && 
!aggregateType.checkCompatibility(type.getPrimitiveType())) {
                 throw new AnalysisException(String.format("Aggregate type %s 
is not compatible with primitive type %s",
                         toString(), type.toSql()));
             }
@@ -341,6 +355,22 @@ public class ColumnDef {
             }
         }
 
+        if (type.getPrimitiveType() == PrimitiveType.AGG_STATE && 
genericAggregationName != null) {
+            if (isKey()) {
+                throw new AnalysisException("AGG_STATE type should not be used 
in key column[" + getName()
+                        + "].");
+            }
+            for (TypeDef def : genericAggregationArguments) {
+                def.analyze(null);
+            }
+        } else if (type.getPrimitiveType() == PrimitiveType.AGG_STATE) {
+            throw new AnalysisException("AGG_STATE type need generic 
aggregation in column[" + getName()
+                    + "].");
+        } else if (genericAggregationName != null) {
+            throw new AnalysisException("generic aggregation need AGG_STATE 
type in column[" + getName()
+                    + "].");
+        }
+
         // If aggregate type is REPLACE_IF_NOT_NULL, we set it nullable.
         // If default value is not set, we set it NULL
         if (aggregateType == AggregateType.REPLACE_IF_NOT_NULL) {
@@ -461,9 +491,21 @@ public class ColumnDef {
     }
 
     public Column toColumn() {
-        return new Column(name, typeDef.getType(), isKey, aggregateType, 
isAllowNull, defaultValue.value, comment,
+        List<Type> typeList = null;
+        List<Boolean> nullableList = null;
+        if (genericAggregationArguments != null) {
+            typeList = 
genericAggregationArguments.stream().map(TypeDef::getType).collect(Collectors.toList());
+            nullableList = 
genericAggregationArguments.stream().map(TypeDef::getNullable).collect(Collectors.toList());
+        }
+
+        Type type = typeDef.getType();
+        if (type.isAggStateType()) {
+            type = new ScalarType(typeList, nullableList);
+        }
+
+        return new Column(name, type, isKey, aggregateType, isAllowNull, 
defaultValue.value, comment,
                 visible, defaultValue.defaultValueExprDef, 
Column.COLUMN_UNIQUE_ID_INIT_VALUE,
-                defaultValue.getValue());
+                defaultValue.getValue(), genericAggregationName, typeList, 
nullableList);
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
index 77e238669c..06422e9b35 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
@@ -665,6 +665,9 @@ public class CreateFunctionStmt extends DdlStmt {
             case QUANTILE_STATE:
                 typeBuilder.setId(Types.PGenericType.TypeId.QUANTILE_STATE);
                 break;
+            case AGG_STATE:
+                typeBuilder.setId(Types.PGenericType.TypeId.AGG_STATE);
+                break;
             case DATE:
                 typeBuilder.setId(Types.PGenericType.TypeId.DATE);
                 break;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/DescribeStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DescribeStmt.java
index 5fb43e3351..eb922ced12 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DescribeStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DescribeStmt.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.AggregateType;
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.DatabaseIf;
 import org.apache.doris.catalog.Env;
@@ -199,7 +200,11 @@ public class DescribeStmt extends ShowStmt {
                             // Extra string (aggregation and bloom filter)
                             List<String> extras = Lists.newArrayList();
                             if (column.getAggregationType() != null) {
-                                extras.add(column.getAggregationType().name());
+                                if (column.getAggregationType() == 
AggregateType.GENERIC_AGGREGATION) {
+                                    
extras.add(column.getGenericAggregationString());
+                                } else {
+                                    
extras.add(column.getAggregationType().name());
+                                }
                             }
                             if (bfColumns != null && 
bfColumns.contains(column.getName())) {
                                 extras.add("BLOOM_FILTER");
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
index bc4c4bc37f..9d7825883a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
@@ -343,7 +343,7 @@ public class SlotDescriptor {
                 .append("id=").append(id)
                 .append(", col=").append(column == null ? "null" : 
column.getName())
                 .append(", colUniqueId=").append(column == null ? "null" : 
column.getUniqueId())
-                .append(", type=").append(type == null ? "null" : 
type.toString())
+                .append(", type=").append(type == null ? "null" : type.toSql())
                 .append(", nullable=").append(isNullable)
                 .append("}")
                 .toString();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java
index 5eae5d57ba..bd46885677 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java
@@ -43,11 +43,17 @@ import java.util.Set;
 public class TypeDef implements ParseNode {
     private boolean isAnalyzed;
     private final Type parsedType;
+    private boolean isNullable = false;
 
     public TypeDef(Type parsedType) {
         this.parsedType = parsedType;
     }
 
+    public TypeDef(Type parsedType, boolean isNullable) {
+        this.parsedType = parsedType;
+        this.isNullable = isNullable;
+    }
+
     public static TypeDef create(PrimitiveType type) {
         return new TypeDef(ScalarType.createType(type));
     }
@@ -297,6 +303,10 @@ public class TypeDef implements ParseNode {
         return parsedType;
     }
 
+    public boolean getNullable() {
+        return isNullable;
+    }
+
     @Override
     public String toString() {
         return parsedType.toSql();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateType.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateType.java
index d3fd46e923..d58330b599 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateType.java
@@ -34,8 +34,8 @@ public enum AggregateType {
     HLL_UNION("HLL_UNION"),
     NONE("NONE"),
     BITMAP_UNION("BITMAP_UNION"),
-    QUANTILE_UNION("QUANTILE_UNION");
-
+    QUANTILE_UNION("QUANTILE_UNION"),
+    GENERIC_AGGREGATION("GENERIC_AGGREGATION");
 
     private static EnumMap<AggregateType, EnumSet<PrimitiveType>> 
compatibilityMap;
 
@@ -99,11 +99,13 @@ public enum AggregateType {
         compatibilityMap.put(MAX, EnumSet.copyOf(primitiveTypeList));
 
         primitiveTypeList.clear();
-        // all types except object stored column type, such as bitmap hll 
quantile_state.
+        // all types except object stored column type, such as bitmap hll
+        // quantile_state.
         EnumSet<PrimitiveType> excObjectStored = 
EnumSet.allOf(PrimitiveType.class);
         excObjectStored.remove(PrimitiveType.BITMAP);
         excObjectStored.remove(PrimitiveType.HLL);
         excObjectStored.remove(PrimitiveType.QUANTILE_STATE);
+        excObjectStored.remove(PrimitiveType.AGG_STATE);
         compatibilityMap.put(REPLACE, EnumSet.copyOf(excObjectStored));
 
         compatibilityMap.put(REPLACE_IF_NOT_NULL, 
EnumSet.copyOf(excObjectStored));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
index 83427f1579..8dbf9e6792 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
@@ -64,12 +64,13 @@ public class Column implements Writable, 
GsonPostProcessable {
     public static final String VERSION_COL = "__DORIS_VERSION_COL__";
     private static final String COLUMN_ARRAY_CHILDREN = "item";
     private static final String COLUMN_STRUCT_CHILDREN = "field";
+    private static final String COLUMN_AGG_ARGUMENT_CHILDREN = "argument";
     public static final int COLUMN_UNIQUE_ID_INIT_VALUE = -1;
     private static final String COLUMN_MAP_KEY = "key";
     private static final String COLUMN_MAP_VALUE = "value";
 
     public static final Column UNSUPPORTED_COLUMN = new Column("unknown",
-            Type.UNSUPPORTED, true, null, true, null, "invalid", true, null, 
-1, null);
+            Type.UNSUPPORTED, true, null, true, null, "invalid", true, null, 
-1, null, null, null, null);
 
     @SerializedName(value = "name")
     private String name;
@@ -122,6 +123,9 @@ public class Column implements Writable, 
GsonPostProcessable {
     @SerializedName(value = "uniqueId")
     private int uniqueId;
 
+    @SerializedName(value = "genericAggregationName")
+    private String genericAggregationName;
+
     private boolean isCompoundKey = false;
 
     public Column() {
@@ -164,18 +168,19 @@ public class Column implements Writable, 
GsonPostProcessable {
     public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
             String defaultValue, String comment) {
         this(name, type, isKey, aggregateType, isAllowNull, defaultValue, 
comment, true, null,
-                COLUMN_UNIQUE_ID_INIT_VALUE, defaultValue);
+                COLUMN_UNIQUE_ID_INIT_VALUE, defaultValue, null, null, null);
     }
 
     public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
             String comment, boolean visible, int colUniqueId) {
         this(name, type, isKey, aggregateType, isAllowNull, null, comment, 
visible, null,
-                colUniqueId, null);
+                colUniqueId, null, null, null, null);
     }
 
     public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
             String defaultValue, String comment, boolean visible, 
DefaultValueExprDef defaultValueExprDef,
-            int colUniqueId, String realDefaultValue) {
+            int colUniqueId, String realDefaultValue, String 
genericAggregationName,
+            List<Type> genericAggregationArguments, List<Boolean> 
nullableList) {
         this.name = name;
         if (this.name == null) {
             this.name = "";
@@ -199,6 +204,15 @@ public class Column implements Writable, 
GsonPostProcessable {
         this.children = new ArrayList<>();
         createChildrenColumn(this.type, this);
         this.uniqueId = colUniqueId;
+
+        this.genericAggregationName = genericAggregationName;
+        if (genericAggregationArguments != null) {
+            for (int i = 0; i < genericAggregationArguments.size(); i++) {
+                Column c = new Column(COLUMN_AGG_ARGUMENT_CHILDREN, 
genericAggregationArguments.get(i));
+                c.setIsAllowNull(nullableList.get(i));
+                addChildrenColumn(c);
+            }
+        }
     }
 
     public Column(Column column) {
@@ -467,6 +481,9 @@ public class Column implements Writable, 
GsonPostProcessable {
         if (null != this.aggregationType) {
             tColumn.setAggregationType(this.aggregationType.toThrift());
         }
+        if (genericAggregationName != null) {
+            tColumn.setAggregation(genericAggregationName);
+        }
         tColumn.setIsKey(this.isKey);
         tColumn.setIsAllowNull(this.isAllowNull);
         // keep compatibility
@@ -475,6 +492,12 @@ public class Column implements Writable, 
GsonPostProcessable {
         toChildrenThrift(this, tColumn);
 
         tColumn.setColUniqueId(uniqueId);
+
+        if (type.isAggStateType()) {
+            for (Column column : children) {
+                tColumn.addToChildrenColumn(column.toThrift());
+            }
+        }
         // ATTN:
         // Currently, this `toThrift()` method is only used from 
CreateReplicaTask.
         // And CreateReplicaTask does not need `defineExpr` field.
@@ -650,6 +673,22 @@ public class Column implements Writable, 
GsonPostProcessable {
         return toSql(isUniqueTable, false);
     }
 
+    public String getGenericAggregationString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(genericAggregationName).append("(");
+        for (int i = 0; i < children.size(); i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(children.get(i).getType().toSql());
+            if (children.get(i).isAllowNull()) {
+                sb.append(" NULL");
+            }
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
     public String toSql(boolean isUniqueTable, boolean isCompatible) {
         StringBuilder sb = new StringBuilder();
         sb.append("`").append(name).append("` ");
@@ -667,7 +706,9 @@ public class Column implements Writable, 
GsonPostProcessable {
         } else {
             sb.append(typeStr);
         }
-        if (aggregationType != null && aggregationType != AggregateType.NONE 
&& !isUniqueTable
+        if (aggregationType == AggregateType.GENERIC_AGGREGATION) {
+            sb.append(" ").append(getGenericAggregationString());
+        } else if (aggregationType != null && aggregationType != 
AggregateType.NONE && !isUniqueTable
                 && !isAggregationTypeImplicit) {
             sb.append(" ").append(aggregationType.name());
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
index 169ae75610..1be7f0d7f3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
@@ -373,9 +373,10 @@ public class HMSExternalTable extends ExternalTable {
         for (FieldSchema field : hmsSchema) {
             tmpSchema.add(new Column(field.getName(),
                     
HiveMetaStoreClientHelper.hiveTypeToDorisType(field.getType(),
-                    IcebergExternalTable.ICEBERG_DATETIME_SCALE_MS), true, 
null,
+                            IcebergExternalTable.ICEBERG_DATETIME_SCALE_MS),
+                    true, null,
                     true, null, field.getComment(), true, null,
-                    
schema.caseInsensitiveFindField(field.getName()).fieldId(), null));
+                    
schema.caseInsensitiveFindField(field.getName()).fieldId(), null, null, null, 
null));
         }
         return tmpSchema;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/IndexSchemaProcNode.java
 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/IndexSchemaProcNode.java
index 20bc7ef270..6e9ae64d94 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/IndexSchemaProcNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/IndexSchemaProcNode.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.common.proc;
 
+import org.apache.doris.catalog.AggregateType;
 import org.apache.doris.catalog.Column;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.FeConstants;
@@ -59,7 +60,11 @@ public class IndexSchemaProcNode implements 
ProcNodeInterface {
             // Extra string (aggregation and bloom filter)
             List<String> extras = Lists.newArrayList();
             if (column.getAggregationType() != null) {
-                extras.add(column.getAggregationType().name());
+                if (column.getAggregationType() == 
AggregateType.GENERIC_AGGREGATION) {
+                    extras.add(column.getGenericAggregationString());
+                } else {
+                    extras.add(column.getAggregationType().name());
+                }
             }
             if (bfColumns != null && bfColumns.contains(column.getName())) {
                 extras.add("BLOOM_FILTER");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
index bca12162cb..f83be84e29 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
@@ -88,6 +88,7 @@ public class Util {
         TYPE_STRING_MAP.put(PrimitiveType.BOOLEAN, "bool");
         TYPE_STRING_MAP.put(PrimitiveType.BITMAP, "bitmap");
         TYPE_STRING_MAP.put(PrimitiveType.QUANTILE_STATE, "quantile_state");
+        TYPE_STRING_MAP.put(PrimitiveType.AGG_STATE, "agg_state");
         TYPE_STRING_MAP.put(PrimitiveType.ARRAY, "array<%s>");
         TYPE_STRING_MAP.put(PrimitiveType.VARIANT, "variant");
         TYPE_STRING_MAP.put(PrimitiveType.NULL_TYPE, "null");
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
index fcb4ae3609..17a74d3eac 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
@@ -39,7 +39,7 @@ import java.util.List;
 public class IntersectCount extends AggregateFunction
         implements ExplicitlyCastableSignature, AlwaysNotNullable, 
BitmapIntersectFunction {
 
-    public static final List<FunctionSignature> SIGNATURES = 
DataType.nonNullNonCharTypes().stream()
+    public static final List<FunctionSignature> SIGNATURES = 
DataType.trivialTypes().stream()
             .map(type -> 
FunctionSignature.ret(BigIntType.INSTANCE).varArgs(BitmapType.INSTANCE, type, 
type))
             .collect(ImmutableList.toImmutableList());
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/AggStateType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/AggStateType.java
new file mode 100644
index 0000000000..84d0d7ce06
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/AggStateType.java
@@ -0,0 +1,103 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.types;
+
+import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.nereids.types.coercion.AbstractDataType;
+import org.apache.doris.nereids.types.coercion.PrimitiveType;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * AggStateType type in Nereids.
+ */
+public class AggStateType extends PrimitiveType {
+
+    public static final AggStateType SYSTEM_DEFAULT = new AggStateType(null, 
null);
+
+    public static final int WIDTH = 16;
+
+    private final List<DataType> subTypes;
+    private final List<Boolean> subTypeNullables;
+
+    public AggStateType(List<DataType> subTypes, List<Boolean> 
subTypeNullables) {
+        this.subTypes = subTypes;
+        this.subTypeNullables = subTypeNullables;
+    }
+
+    @Override
+    public Type toCatalogDataType() {
+        List<Type> types = subTypes.stream().map(t -> 
t.toCatalogDataType()).collect(Collectors.toList());
+        return new ScalarType(types, subTypeNullables);
+    }
+
+    @Override
+    public boolean acceptsType(AbstractDataType other) {
+        return other instanceof AggStateType;
+    }
+
+    @Override
+    public String simpleString() {
+        return "agg_state";
+    }
+
+    @Override
+    public DataType defaultConcreteType() {
+        return SYSTEM_DEFAULT;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof AggStateType)) {
+            return false;
+        }
+
+        AggStateType rhs = (AggStateType) o;
+        if ((subTypes == null) != (rhs.subTypes == null)) {
+            return false;
+        }
+        if (subTypes == null) {
+            return true;
+        }
+        if (subTypes.size() != rhs.subTypes.size()) {
+            return false;
+        }
+
+        for (int i = 0; i < subTypes.size(); i++) {
+            if (!subTypes.get(i).equals(rhs.subTypes.get(i))) {
+                return false;
+            }
+            if (!subTypeNullables.get(i).equals(rhs.subTypeNullables.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int width() {
+        return WIDTH;
+    }
+
+    @Override
+    public String toSql() {
+        return toCatalogDataType().toSql();
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
index ff40f922a7..2bdde01ced 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 /**
  * Abstract class for all data type in Nereids.
@@ -306,6 +307,10 @@ public abstract class DataType implements AbstractDataType 
{
             // TODO: support array type really
             org.apache.doris.catalog.ArrayType arrayType = 
(org.apache.doris.catalog.ArrayType) type;
             return ArrayType.of(fromCatalogType(arrayType.getItemType()), 
arrayType.getContainsNull());
+        } else if (type.isAggStateType()) {
+            List<DataType> types = ((ScalarType) 
type).getSubTypes().stream().map(t -> fromCatalogType(t))
+                    .collect(Collectors.toList());
+            return new AggStateType(types, ((ScalarType) 
type).getSubTypeNullables());
         }
         throw new AnalysisException("Nereids do not support type: " + type);
     }
@@ -491,6 +496,10 @@ public abstract class DataType implements AbstractDataType 
{
         return this instanceof QuantileStateType;
     }
 
+    public boolean isAggStateType() {
+        return this instanceof AggStateType;
+    }
+
     public boolean isHllType() {
         return this instanceof HllType;
     }
@@ -563,6 +572,13 @@ public abstract class DataType implements AbstractDataType 
{
         }
     }
 
+    public static List<DataType> trivialTypes() {
+        return Type.getTrivialTypes()
+                .stream()
+                .map(DataType::fromCatalogType)
+                .collect(ImmutableList.toImmutableList());
+    }
+
     public static List<DataType> supportedTypes() {
         return Type.getSupportedTypes()
                 .stream()
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/HllType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/HllType.java
index 59589226c5..5c0c322505 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/HllType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/HllType.java
@@ -22,7 +22,7 @@ import 
org.apache.doris.nereids.types.coercion.AbstractDataType;
 import org.apache.doris.nereids.types.coercion.PrimitiveType;
 
 /**
- * Bitmap type in Nereids.
+ * HyperLogLog type in Nereids.
  */
 public class HllType extends PrimitiveType {
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/QuantileStateType.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/QuantileStateType.java
index 60133a16e2..7c223e649a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/QuantileStateType.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/QuantileStateType.java
@@ -22,7 +22,7 @@ import 
org.apache.doris.nereids.types.coercion.AbstractDataType;
 import org.apache.doris.nereids.types.coercion.PrimitiveType;
 
 /**
- * Bitmap type in Nereids.
+ * QuantileState type in Nereids.
  */
 public class QuantileStateType extends PrimitiveType {
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
index c919d7116b..cfdbfa684e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
@@ -798,7 +798,7 @@ public class TypeCoercionUtils {
 
     private static boolean maybeCastToVarchar(DataType t) {
         return t.isVarcharType() || t.isCharType() || t.isTimeType() || 
t.isTimeV2Type() || t.isJsonType()
-                || t.isHllType() || t.isBitmapType() || 
t.isQuantileStateType();
+                || t.isHllType() || t.isBitmapType() || 
t.isQuantileStateType() || t.isAggStateType();
     }
 
     @Developing
diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex 
b/fe/fe-core/src/main/jflex/sql_scanner.flex
index 987be26b40..e51fc57049 100644
--- a/fe/fe-core/src/main/jflex/sql_scanner.flex
+++ b/fe/fe-core/src/main/jflex/sql_scanner.flex
@@ -367,6 +367,7 @@ import org.apache.doris.qe.SqlModeHelper;
         keywordMap.put("property", new Integer(SqlParserSymbols.KW_PROPERTY));
         keywordMap.put("quantile_state", new 
Integer(SqlParserSymbols.KW_QUANTILE_STATE));
         keywordMap.put("quantile_union", new 
Integer(SqlParserSymbols.KW_QUANTILE_UNION));
+        keywordMap.put("agg_state", new 
Integer(SqlParserSymbols.KW_AGG_STATE));
         keywordMap.put("query", new Integer(SqlParserSymbols.KW_QUERY));
         keywordMap.put("quota", new Integer(SqlParserSymbols.KW_QUOTA));
         keywordMap.put("random", new Integer(SqlParserSymbols.KW_RANDOM));
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
index 244b7c9288..ce104c955b 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
@@ -79,7 +79,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     /* Case2 without output explode column
@@ -95,7 +95,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     /* Case3 group by explode column
@@ -116,7 +116,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=varchar(*)"));
         // group by tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=2, 
tbl=null, byteSize=32}"));
     }
@@ -135,7 +135,7 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("PREDICATES: `e1` = '1'"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     /* Case5 where normal column
@@ -151,7 +151,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
colUniqueId=-1, type=varchar(*)"));
         
Assert.assertTrue(UtFrameUtils.checkPlanResultContainsNode(explainString, 0, 
"OlapScanNode"));
         Assert.assertTrue(explainString.contains("PREDICATES: `k1` = 1"));
     }
@@ -171,10 +171,10 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 1 
2"));
         // lateral view 2 tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp2, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e2, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e2, 
colUniqueId=-1, type=varchar(*)"));
         // lateral view 1 tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=2, 
tbl=tmp1, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     // test explode_split function
@@ -203,7 +203,7 @@ public class TableFunctionPlanTest {
         String sql = "explain select k1 from db1.tbl1 where explode_split(k2, 
\",\");";
         String explainString = UtFrameUtils.getSQLPlanOrErrorMsg(ctx, sql);
         Assert.assertTrue(
-                explainString.contains("No matching function with signature: 
explode_split(varchar(1), varchar(-1))."));
+                explainString.contains("No matching function with signature: 
explode_split(varchar(1), varchar(*))."));
     }
 
     // test projection
@@ -350,8 +350,8 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(concat(`a`.`k2`, ',', `a`.`k3`), ',')"));
         Assert.assertTrue(explainString.contains("lateral view tuple id: 1"));
         Assert.assertTrue(explainString.contains("output slot id: 3"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=0, col=k2, 
colUniqueId=1, type=VARCHAR(1)"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=k3, 
colUniqueId=2, type=VARCHAR(1)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=0, col=k2, 
colUniqueId=1, type=varchar(1)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=k3, 
colUniqueId=2, type=varchar(1)"));
     }
 
     // lateral view of subquery
@@ -368,7 +368,7 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 2"));
         Assert.assertTrue(explainString.contains("output slot id: 2"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 2"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     /*
@@ -384,7 +384,7 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 3"));
         Assert.assertTrue(explainString.contains("output slot id: 3"));
         Assert.assertTrue(explainString.contains("tuple ids: 1 3"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=3, col=e1, 
colUniqueId=-1, type=VARCHAR(*)"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=3, col=e1, 
colUniqueId=-1, type=varchar(*)"));
     }
 
     /*
@@ -403,19 +403,19 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("tuple ids: 1 3"));
         String formatString = explainString.replaceAll(" ", "");
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=0,col=k1,colUniqueId=0,type=INT"
+                "SlotDescriptor{id=0,col=k1,colUniqueId=0,type=int"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=1,col=k2,colUniqueId=1,type=VARCHAR(1)"
+                "SlotDescriptor{id=1,col=k2,colUniqueId=1,type=varchar(1)"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=2,col=k1,colUniqueId=0,type=INT"
+                "SlotDescriptor{id=2,col=k1,colUniqueId=0,type=int"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=3,col=null,colUniqueId=null,type=VARCHAR(*)"
+                "SlotDescriptor{id=3,col=null,colUniqueId=null,type=varchar(*)"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=6,col=e1,colUniqueId=-1,type=VARCHAR(*)"
+                "SlotDescriptor{id=6,col=e1,colUniqueId=-1,type=varchar(*)"
         ));
     }
 
diff --git a/regression-test/data/types/test_show_data_types.out 
b/regression-test/data/types/test_show_data_types.out
index efdc170576..fe820a5c7f 100644
--- a/regression-test/data/types/test_show_data_types.out
+++ b/regression-test/data/types/test_show_data_types.out
@@ -1,5 +1,6 @@
 -- This file is automatically generated. You should know what you did if you 
want to edit this
 -- !sql --
+AGG_STATE      16
 ARRAY  32
 BIGINT 8
 BITMAP 16
diff --git a/regression-test/suites/nereids_syntax_p0/explain.groovy 
b/regression-test/suites/nereids_syntax_p0/explain.groovy
index 3a98d42f62..0d6fa5e769 100644
--- a/regression-test/suites/nereids_syntax_p0/explain.groovy
+++ b/regression-test/suites/nereids_syntax_p0/explain.groovy
@@ -61,7 +61,7 @@ suite("nereids_explain") {
             when 1>1 then cast(1 as float)
             else 0.0 end;
             """
-        contains "SlotDescriptor{id=0, col=null, colUniqueId=null, 
type=DECIMAL(14, 7), nullable=false}"
+        contains "SlotDescriptor{id=0, col=null, colUniqueId=null, 
type=decimal(14, 7), nullable=false}"
     }
 
     def explainStr = sql("select sum(if(lo_tax=1,lo_tax,0)) from lineorder 
where false").toString()


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to