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

nextdreamblue 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 5853833325b [enhancement](prepared statement) Handle unsigned numeric 
type in prepare statement (#36133)
5853833325b is described below

commit 5853833325b576df080c9b561ba6b1decdca20b4
Author: xy720 <22125576+xy...@users.noreply.github.com>
AuthorDate: Mon Jun 17 11:24:19 2024 +0800

    [enhancement](prepared statement) Handle unsigned numeric type in prepare 
statement (#36133)
    
    
    Now we still can not handle unsigned type in prepare statement.
    
    According to the docs of Mysql Binary Protocol [mysql
    
docs](https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query.html).
    The `param_type_and_flag` flag which indicate a type has 2 bytes.
    
    e.g.
    
    1. For signed type:
    
    ```
    +----------+------------------+---------------------+
    | typecode | binary           | type                |
    +----------+------------------+---------------------+
    |        1 | 0000000000000001 | MYSQL_TYPE_TINY     |
    |        2 | 0000000000000010 | MYSQL_TYPE_SHORT    |
    |        3 | 0000000000000011 | MYSQL_TYPE_LONG     |
    |        8 | 0000000000001000 | MYSQL_TYPE_LONGLONG |
    +----------+------------------+---------------------+
    ```
    
    2. For unsigned type:
    
    ```
    +----------+------------------+---------------------+
    | typecode | binary           | type                |
    +----------+------------------+---------------------+
    |        1 | 1000000000000001 | MYSQL_TYPE_TINY     |
    |        2 | 1000000000000010 | MYSQL_TYPE_SHORT    |
    |        3 | 1000000000000011 | MYSQL_TYPE_LONG     |
    |        8 | 1000000000001000 | MYSQL_TYPE_LONGLONG |
    +----------+------------------+---------------------+
    ```
    
    (The mapping between code and type can reference: [mysql
    
docs](https://dev.mysql.com/doc/dev/mysql-server/latest/field__types_8h_source.html))
    
    The MSB of the 2 bytes is reserved for unsigned flag.
    
    Now, when we encountered an unsigned long long in prepared statement, we
    will meet code 1000000000001000, which is 32776 in integer, then a
    NullPointerException will be thrown:
    
    ```
    java.lang.NullPointerException: Cannot invoke 
"org.apache.doris.qe.StmtExecutor.getParsedStmt()" because "this.executor" is 
null
            at 
org.apache.doris.qe.MysqlConnectProcessor.handleExecute(MysqlConnectProcessor.java:208)
 ~[doris-fe.jar:1.2-SNAPSHOT]
            at 
org.apache.doris.qe.MysqlConnectProcessor.handleExecute(MysqlConnectProcessor.java:242)
 ~[doris-fe.jar:1.2-SNAPSHOT]
            at 
org.apache.doris.qe.MysqlConnectProcessor.dispatch(MysqlConnectProcessor.java:287)
 ~[doris-fe.jar:1.2-SNAPSHOT]
            at 
org.apache.doris.qe.MysqlConnectProcessor.processOnce(MysqlConnectProcessor.java:337)
 ~[doris-fe.jar:1.2-SNAPSHOT]
            at 
org.apache.doris.mysql.ReadListener.lambda$handleEvent$0(ReadListener.java:52) 
~[doris-fe.jar:1.2-SNAPSHOT]
            at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) 
~[?:?]
            at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) 
~[?:?]
            at java.lang.Thread.run(Thread.java:840) ~[?:?]
    ```
    
    So this commit will handle the situation mentioned above.
    
    If an unsigned numeric type is encountered, we convert it by using
    larger data types. For example, we can use small int to represent
    unsigned tiny int (0-255), big int to represent unsigned ints (0-2 ^
    32-1), and so on.
---
 .../org/apache/doris/catalog/MysqlColType.java     | 11 ++-
 .../org/apache/doris/analysis/DateLiteral.java     |  2 +-
 .../org/apache/doris/analysis/DecimalLiteral.java  |  2 +-
 .../org/apache/doris/analysis/FloatLiteral.java    |  2 +-
 .../java/org/apache/doris/analysis/IntLiteral.java |  9 +-
 .../org/apache/doris/analysis/LargeIntLiteral.java |  5 ++
 .../org/apache/doris/analysis/LiteralExpr.java     | 98 +++++++++++-----------
 .../org/apache/doris/analysis/PlaceHolderExpr.java | 16 +++-
 .../org/apache/doris/analysis/StringLiteral.java   |  2 +-
 .../apache/doris/common/util/ByteBufferUtil.java   | 34 ++++++++
 .../nereids/trees/expressions/Placeholder.java     | 14 +++-
 .../nereids/trees/expressions/literal/Literal.java | 51 ++++++++---
 .../org/apache/doris/qe/MysqlConnectProcessor.java |  9 +-
 13 files changed, 176 insertions(+), 79 deletions(-)

diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/catalog/MysqlColType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/MysqlColType.java
index cd48b0afd94..0b7e9ab22b9 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/MysqlColType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/MysqlColType.java
@@ -60,6 +60,10 @@ public enum MysqlColType {
 
     private static final Map<Integer, MysqlColType> CODE_MAP = new HashMap<>();
 
+    public static final int MYSQL_CODE_MASK = 0xFF;
+
+    public static final int UNSIGNED_MASK = 0x8000;
+
     static {
         for (MysqlColType type : MysqlColType.values()) {
             CODE_MAP.put(type.code, type);
@@ -89,7 +93,12 @@ public enum MysqlColType {
     }
 
     public static MysqlColType fromCode(int code) {
-        return CODE_MAP.get(code);
+        // Use the lower 8 bits of the code.
+        return CODE_MAP.get(code & MYSQL_CODE_MASK);
+    }
+
+    public static boolean isUnsigned(int code) {
+        return (code & MysqlColType.UNSIGNED_MASK) != 0;
     }
 
     public String getJdbcColumnTypeName() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
index 0a2d21c426e..3043656b836 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
@@ -1776,7 +1776,7 @@ public class DateLiteral extends LiteralExpr {
     }
 
     @Override
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         int len = getParmLen(data);
         if (type.getPrimitiveType() == PrimitiveType.DATE) {
             if (len >= 4) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
index d4c009f74d5..e550df64871 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
@@ -404,7 +404,7 @@ public class DecimalLiteral extends NumericLiteralExpr {
     }
 
     @Override
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         int len = getParmLen(data);
         BigDecimal v = null;
         try {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
index 53225afbf71..5a8544e61a6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
@@ -267,7 +267,7 @@ public class FloatLiteral extends NumericLiteralExpr {
     }
 
     @Override
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         if (type.getPrimitiveType() == PrimitiveType.FLOAT) {
             value = data.getFloat();
             return;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
index b7559da4aad..f4724d229cf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.NotImplementedException;
+import org.apache.doris.common.util.ByteBufferUtil;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.thrift.TExprNode;
 import org.apache.doris.thrift.TExprNodeType;
@@ -374,19 +375,19 @@ public class IntLiteral extends NumericLiteralExpr {
     }
 
     @Override
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         switch (type.getPrimitiveType()) {
             case TINYINT:
                 value = data.get();
                 break;
             case SMALLINT:
-                value = data.getChar();
+                value = !isUnsigned ? data.getChar() : 
ByteBufferUtil.getUnsignedByte(data);
                 break;
             case INT:
-                value = data.getInt();
+                value = !isUnsigned ? data.getInt() : 
ByteBufferUtil.getUnsignedShort(data);
                 break;
             case BIGINT:
-                value = data.getLong();
+                value = !isUnsigned ? data.getLong() : 
ByteBufferUtil.getUnsignedInt(data);
                 break;
             default:
                 Preconditions.checkState(false);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java
index 7dc6306cf4d..a45551e971a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java
@@ -237,6 +237,11 @@ public class LargeIntLiteral extends NumericLiteralExpr {
         return super.uncheckedCastTo(targetType);
     }
 
+    @Override
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
+        value = new BigInteger(Long.toUnsignedString(data.getLong()));
+    }
+
     @Override
     public void swapSign() {
         // swapping sign does not change the type
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
index 3f7263d1637..1dfd952eb10 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
@@ -20,6 +20,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.MysqlColType;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Type;
@@ -333,54 +334,57 @@ public abstract class LiteralExpr extends Expr implements 
Comparable<LiteralExpr
         return getStringValue();
     }
 
-    public static LiteralExpr getLiteralByMysqlType(int mysqlType) throws 
AnalysisException {
-        switch (mysqlType) {
-            // MYSQL_TYPE_TINY
-            case 1:
-                return LiteralExpr.create("0", Type.TINYINT);
-            // MYSQL_TYPE_SHORT
-            case 2:
-                return LiteralExpr.create("0", Type.SMALLINT);
-            // MYSQL_TYPE_LONG
-            case 3:
-                return LiteralExpr.create("0", Type.INT);
-            // MYSQL_TYPE_LONGLONG
-            case 8:
-                return LiteralExpr.create("0", Type.BIGINT);
-            // MYSQL_TYPE_FLOAT
-            case 4:
-                return LiteralExpr.create("0", Type.FLOAT);
-            // MYSQL_TYPE_DOUBLE
-            case 5:
-                return LiteralExpr.create("0", Type.DOUBLE);
-            // MYSQL_TYPE_DECIMAL
-            case 0:
-            // MYSQL_TYPE_NEWDECIMAL
-            case 246:
-                return LiteralExpr.create("0", Type.DECIMAL32);
-            // MYSQL_TYPE_TIME
-            case 11:
-                return LiteralExpr.create("", Type.TIME);
-            // MYSQL_TYPE_DATE
-            case 10:
-                return LiteralExpr.create("1970-01-01", Type.DATE);
-            // MYSQL_TYPE_DATETIME
-            case 12:
-            // MYSQL_TYPE_TIMESTAMP
-            case 7:
-            // MYSQL_TYPE_TIMESTAMP2
-            case 17:
-                return LiteralExpr.create("1970-01-01 00:00:00", 
Type.DATETIME);
-            // MYSQL_TYPE_STRING
-            case 254:
-            case 253:
-                return LiteralExpr.create("", Type.STRING);
-            // MYSQL_TYPE_VARCHAR
-            case 15:
-                return LiteralExpr.create("", Type.VARCHAR);
+    public static LiteralExpr getLiteralByMysqlType(int mysqlType, boolean 
isUnsigned) throws AnalysisException {
+        LiteralExpr literalExpr = null;
+
+        // If this is an unsigned numeric type, we convert it by using larger 
data types. For example, we can use
+        // small int to represent unsigned tiny int (0-255), big int to 
represent unsigned ints (0-2 ^ 32-1),
+        // and so on.
+        switch (mysqlType & MysqlColType.MYSQL_CODE_MASK) {
+            case 1: // MYSQL_TYPE_TINY
+                literalExpr = LiteralExpr.create("0", !isUnsigned ? 
Type.TINYINT : Type.SMALLINT);
+                break;
+            case 2: // MYSQL_TYPE_SHORT
+                literalExpr = LiteralExpr.create("0", !isUnsigned ? 
Type.SMALLINT : Type.INT);
+                break;
+            case 3: // MYSQL_TYPE_LONG
+                literalExpr = LiteralExpr.create("0", !isUnsigned ? Type.INT : 
Type.BIGINT);
+                break;
+            case 8: // MYSQL_TYPE_LONGLONG
+                literalExpr = LiteralExpr.create("0", !isUnsigned ? 
Type.BIGINT : Type.LARGEINT);
+                break;
+            case 4: // MYSQL_TYPE_FLOAT
+                literalExpr = LiteralExpr.create("0", Type.FLOAT);
+                break;
+            case 5: // MYSQL_TYPE_DOUBLE
+                literalExpr = LiteralExpr.create("0", Type.DOUBLE);
+                break;
+            case 0: // MYSQL_TYPE_DECIMAL
+            case 246: // MYSQL_TYPE_NEWDECIMAL
+                literalExpr = LiteralExpr.create("0", Type.DECIMAL32);
+                break;
+            case 11: // MYSQL_TYPE_TIME
+                literalExpr = LiteralExpr.create("", Type.TIME);
+                break;
+            case 10: // MYSQL_TYPE_DATE
+                literalExpr = LiteralExpr.create("1970-01-01", Type.DATE);
+                break;
+            case 12: // MYSQL_TYPE_DATETIME
+            case 7: // MYSQL_TYPE_TIMESTAMP
+            case 17: // MYSQL_TYPE_TIMESTAMP2
+                literalExpr = LiteralExpr.create("1970-01-01 00:00:00", 
Type.DATETIME);
+                break;
+            case 254: // MYSQL_TYPE_STRING
+            case 253: // MYSQL_TYPE_VAR_STRING
+                literalExpr = LiteralExpr.create("", Type.STRING);
+                break;
+            case 15: // MYSQL_TYPE_VARCHAR
+                literalExpr = LiteralExpr.create("", Type.VARCHAR);
+                break;
             default:
-                return null;
+                throw new AnalysisException("Unsupported MySQL type: " + 
mysqlType);
         }
+        return literalExpr;
     }
 
     @Override
@@ -485,7 +489,7 @@ public abstract class LiteralExpr extends Expr implements 
Comparable<LiteralExpr
     // Parse from binary data, the format follows mysql binary protocal
     // see 
https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_binary_resultset.html.
     // Return next offset
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         Preconditions.checkState(false,
                 "should implement this in derived class. " + 
this.type.toSql());
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java
index 4a03015c965..ca0596258f6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.MysqlColType;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
@@ -59,7 +60,7 @@ public class PlaceHolderExpr extends LiteralExpr {
 
     public LiteralExpr createLiteralFromType() throws AnalysisException {
         Preconditions.checkState(mysqlTypeCode > 0);
-        return LiteralExpr.getLiteralByMysqlType(mysqlTypeCode);
+        return LiteralExpr.getLiteralByMysqlType(mysqlTypeCode, isUnsigned());
     }
 
     public static PlaceHolderExpr create(String value, Type type) throws 
AnalysisException {
@@ -86,6 +87,10 @@ public class PlaceHolderExpr extends LiteralExpr {
         return lExpr.isMinValue();
     }
 
+    public boolean isUnsigned() {
+        return MysqlColType.isUnsigned(mysqlTypeCode);
+    }
+
     @Override
     public int compareLiteral(LiteralExpr expr) {
         return lExpr.compareLiteral(expr);
@@ -129,6 +134,11 @@ public class PlaceHolderExpr extends LiteralExpr {
         return "?";
     }
 
+    @Override
+    protected Expr uncheckedCastTo(Type targetType) throws AnalysisException {
+        return this.lExpr.uncheckedCastTo(targetType);
+    }
+
     // Swaps the sign of numeric literals.
     // Throws for non-numeric literals.
     public void swapSign() throws NotImplementedException {
@@ -175,7 +185,7 @@ public class PlaceHolderExpr extends LiteralExpr {
         return "\"" + getStringValue() + "\"";
     }
 
-    public void setupParamFromBinary(ByteBuffer data) {
-        lExpr.setupParamFromBinary(data);
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
+        lExpr.setupParamFromBinary(data, isUnsigned);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
index 2987baf9a97..806c0cc2ed3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
@@ -334,7 +334,7 @@ public class StringLiteral extends LiteralExpr {
     }
 
     @Override
-    public void setupParamFromBinary(ByteBuffer data) {
+    public void setupParamFromBinary(ByteBuffer data, boolean isUnsigned) {
         int strLen = getParmLen(data);
         if (strLen > data.remaining()) {
             strLen = data.remaining();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/ByteBufferUtil.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/ByteBufferUtil.java
new file mode 100644
index 00000000000..4ec8f01149a
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/ByteBufferUtil.java
@@ -0,0 +1,34 @@
+// 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.common.util;
+
+import java.nio.ByteBuffer;
+
+public class ByteBufferUtil {
+    public static short getUnsignedByte(ByteBuffer buffer) {
+        return (short) (buffer.get() & 0xFF);
+    }
+
+    public static int getUnsignedShort(ByteBuffer buffer) {
+        return buffer.getShort() & 0xFFFF;
+    }
+
+    public static long getUnsignedInt(ByteBuffer buffer) {
+        return buffer.getInt() & 0xFFFFFFFFL;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
index 9ae054d82a6..0432beadd2c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
@@ -33,15 +33,17 @@ import java.util.Optional;
 public class Placeholder extends Expression implements LeafExpression {
     private final PlaceholderId placeholderId;
     private final Optional<MysqlColType> mysqlColType;
+    private int mysqlTypeCode = -1;
 
     public Placeholder(PlaceholderId placeholderId) {
         this.placeholderId = placeholderId;
         this.mysqlColType = Optional.empty();
     }
 
-    public Placeholder(PlaceholderId placeholderId, MysqlColType mysqlColType) 
{
+    public Placeholder(PlaceholderId placeholderId, int mysqlTypeCode) {
         this.placeholderId = placeholderId;
-        this.mysqlColType = Optional.of(mysqlColType);
+        this.mysqlColType = Optional.of(MysqlColType.fromCode(mysqlTypeCode));
+        this.mysqlTypeCode = mysqlTypeCode;
     }
 
     public PlaceholderId getPlaceholderId() {
@@ -68,8 +70,12 @@ public class Placeholder extends Expression implements 
LeafExpression {
         return NullType.INSTANCE;
     }
 
-    public Placeholder withNewMysqlColType(MysqlColType mysqlColType) {
-        return new Placeholder(getPlaceholderId(), mysqlColType);
+    public Placeholder withNewMysqlColType(int mysqlTypeCode) {
+        return new Placeholder(getPlaceholderId(), mysqlTypeCode);
+    }
+
+    public boolean isUnsigned() {
+        return MysqlColType.isUnsigned(mysqlTypeCode);
     }
 
     public MysqlColType getMysqlColType() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
index d81206f7100..4619e35d5e0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
@@ -22,6 +22,7 @@ import org.apache.doris.analysis.LiteralExpr;
 import org.apache.doris.catalog.MysqlColType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.Config;
+import org.apache.doris.common.util.ByteBufferUtil;
 import org.apache.doris.mysql.MysqlProto;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.exceptions.UnboundException;
@@ -448,42 +449,68 @@ public abstract class Literal extends Expression 
implements LeafExpression, Comp
      * Retrieves a Literal object based on the MySQL type and the data 
provided.
      *
      * @param mysqlType the MySQL type identifier
+     * @param isUnsigned true if it is an unsigned type
      * @param data      the ByteBuffer containing the data
      * @return a Literal object corresponding to the MySQL type
      * @throws AnalysisException if the MySQL type is unsupported or if data 
conversion fails
      * @link  <a 
href="https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_binary_resultset.html";>...</a>.
      */
-    public static Literal getLiteralByMysqlType(MysqlColType mysqlType, 
ByteBuffer data) throws AnalysisException {
+    public static Literal getLiteralByMysqlType(MysqlColType mysqlType, 
boolean isUnsigned, ByteBuffer data)
+            throws AnalysisException {
+        Literal literal = null;
+        // If this is an unsigned numeric type, we convert it by using larger 
data types. For example, we can use
+        // small int to represent unsigned tiny int (0-255), big int to 
represent unsigned ints (0-2 ^ 32-1),
+        // and so on.
         switch (mysqlType) {
             case MYSQL_TYPE_TINY:
-                return new TinyIntLiteral(data.get());
+                literal = !isUnsigned
+                    ? new TinyIntLiteral(data.get()) :
+                        new 
SmallIntLiteral(ByteBufferUtil.getUnsignedByte(data));
+                break;
             case MYSQL_TYPE_SHORT:
-                return new SmallIntLiteral((short) data.getChar());
+                literal = !isUnsigned
+                    ? new SmallIntLiteral((short) data.getChar()) :
+                        new 
IntegerLiteral(ByteBufferUtil.getUnsignedShort(data));
+                break;
             case MYSQL_TYPE_LONG:
-                return new IntegerLiteral(data.getInt());
+                literal = !isUnsigned
+                    ? new IntegerLiteral(data.getInt()) :
+                        new BigIntLiteral(ByteBufferUtil.getUnsignedInt(data));
+                break;
             case MYSQL_TYPE_LONGLONG:
-                return new BigIntLiteral(data.getLong());
+                literal = !isUnsigned
+                    ? new BigIntLiteral(data.getLong()) :
+                        new LargeIntLiteral(new 
BigInteger(Long.toUnsignedString(data.getLong())));
+                break;
             case MYSQL_TYPE_FLOAT:
-                return new FloatLiteral(data.getFloat());
+                literal = new FloatLiteral(data.getFloat());
+                break;
             case MYSQL_TYPE_DOUBLE:
-                return new DoubleLiteral(data.getDouble());
+                literal = new DoubleLiteral(data.getDouble());
+                break;
             case MYSQL_TYPE_DECIMAL:
             case MYSQL_TYPE_NEWDECIMAL:
-                return handleDecimalLiteral(data);
+                literal = handleDecimalLiteral(data);
+                break;
             case MYSQL_TYPE_DATE:
-                return handleDateLiteral(data);
+                literal = handleDateLiteral(data);
+                break;
             case MYSQL_TYPE_DATETIME:
             case MYSQL_TYPE_TIMESTAMP:
             case MYSQL_TYPE_TIMESTAMP2:
-                return handleDateTimeLiteral(data);
+                literal = handleDateTimeLiteral(data);
+                break;
             case MYSQL_TYPE_STRING:
             case MYSQL_TYPE_VARSTRING:
-                return handleStringLiteral(data);
+                literal = handleStringLiteral(data);
+                break;
             case MYSQL_TYPE_VARCHAR:
-                return handleVarcharLiteral(data);
+                literal = handleVarcharLiteral(data);
+                break;
             default:
                 throw new AnalysisException("Unsupported MySQL type: " + 
mysqlType);
         }
+        return literal;
     }
 
     private static Literal handleDecimalLiteral(ByteBuffer data) throws 
AnalysisException {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java
index 5480e964f28..ae5d327c656 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java
@@ -120,7 +120,8 @@ public class MysqlConnectProcessor extends ConnectProcessor 
{
                         continue;
                     }
                     LiteralExpr l = 
prepareStmt.placeholders().get(i).createLiteralFromType();
-                    l.setupParamFromBinary(packetBuf);
+                    boolean isUnsigned = 
prepareStmt.placeholders().get(i).isUnsigned();
+                    l.setupParamFromBinary(packetBuf, isUnsigned);
                     realValueExprs.add(l);
                 }
             }
@@ -167,8 +168,7 @@ public class MysqlConnectProcessor extends ConnectProcessor 
{
                         LOG.debug("code {}", typeCode);
                         // assign type to placeholders
                         typedPlaceholders.add(
-                                prepareCommand.getPlaceholders().get(i)
-                                        
.withNewMysqlColType(MysqlColType.fromCode(typeCode)));
+                                
prepareCommand.getPlaceholders().get(i).withNewMysqlColType(typeCode));
                     }
                     // rewrite with new prepared statment with type info in 
placeholders
                     prepCtx.command = 
prepareCommand.withPlaceholders(typedPlaceholders);
@@ -183,7 +183,8 @@ public class MysqlConnectProcessor extends ConnectProcessor 
{
                         continue;
                     }
                     MysqlColType type = 
prepareCommand.getPlaceholders().get(i).getMysqlColType();
-                    Literal l = Literal.getLiteralByMysqlType(type, packetBuf);
+                    boolean isUnsigned = 
prepareCommand.getPlaceholders().get(i).isUnsigned();
+                    Literal l = Literal.getLiteralByMysqlType(type, 
isUnsigned, packetBuf);
                     statementContext.getIdToPlaceholderRealExpr().put(exprId, 
l);
                 }
             }


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

Reply via email to