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