eldenmoon commented on code in PR #35318: URL: https://github.com/apache/doris/pull/35318#discussion_r1616900076
########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/PlaceholderExpr.java: ########## @@ -0,0 +1,82 @@ +// 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.trees.expressions; + +import org.apache.doris.catalog.MysqlColType; +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DataType; + +/** + * Placeholder for prepared statement + */ +public class PlaceholderExpr extends Expression { + private final int exprId; + private Expression expr; + + private MysqlColType mysqlTypeCode; + + public PlaceholderExpr(int exprId) { + this.exprId = exprId; + } + + protected PlaceholderExpr(int exprId, Expression expr) { + this.exprId = exprId; + this.expr = expr; + } + + public Expression getExpr() { + return expr; + } + + public int getExprId() { + return exprId; + } + + public void setExpr(Expression expr) { + this.expr = expr; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitPlaceholderExpr(this, context); + } + + public void setTypeCode(int mysqlTypeCode) { + this.mysqlTypeCode = MysqlColType.fromCode(mysqlTypeCode); Review Comment: done ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java: ########## @@ -396,4 +400,153 @@ public boolean isZero() { } return false; } + + /** + ** get paramter length, port from mysql get_param_length + **/ + public static int getParmLen(ByteBuffer data) { + int maxLen = data.remaining(); + if (maxLen < 1) { + return 0; + } + // get and advance 1 byte + int len = MysqlProto.readInt1(data); + if (len == 252) { + if (maxLen < 3) { + return 0; + } + // get and advance 2 bytes + return MysqlProto.readInt2(data); + } else if (len == 253) { + if (maxLen < 4) { + return 0; + } + // get and advance 3 bytes + return MysqlProto.readInt3(data); + } else if (len == 254) { + /* + In our client-server protocol all numbers bigger than 2^24 + stored as 8 bytes with uint8korr. Here we always know that + parameter length is less than 2^4 so we don't look at the second + 4 bytes. But still we need to obey the protocol hence 9 in the + assignment below. + */ + if (maxLen < 9) { + return 0; + } + len = MysqlProto.readInt4(data); + MysqlProto.readFixedString(data, 4); + return len; + } else if (len == 255) { + return 0; + } else { + return len; + } + } + + /** + * Retrieves a Literal object based on the MySQL type and the data provided. Review Comment: done ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java: ########## @@ -396,4 +400,153 @@ public boolean isZero() { } return false; } + + /** + ** get paramter length, port from mysql get_param_length + **/ + public static int getParmLen(ByteBuffer data) { + int maxLen = data.remaining(); + if (maxLen < 1) { + return 0; + } + // get and advance 1 byte + int len = MysqlProto.readInt1(data); + if (len == 252) { + if (maxLen < 3) { + return 0; + } + // get and advance 2 bytes + return MysqlProto.readInt2(data); + } else if (len == 253) { + if (maxLen < 4) { + return 0; + } + // get and advance 3 bytes + return MysqlProto.readInt3(data); + } else if (len == 254) { + /* + In our client-server protocol all numbers bigger than 2^24 + stored as 8 bytes with uint8korr. Here we always know that + parameter length is less than 2^4 so we don't look at the second + 4 bytes. But still we need to obey the protocol hence 9 in the + assignment below. + */ + if (maxLen < 9) { + return 0; + } + len = MysqlProto.readInt4(data); + MysqlProto.readFixedString(data, 4); + return len; + } else if (len == 255) { + return 0; + } else { + return len; + } + } + + /** + * Retrieves a Literal object based on the MySQL type and the data provided. + * + * @param mysqlType the MySQL type identifier + * @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 + */ + public static Literal getLiteralByMysqlType(MysqlColType mysqlType, ByteBuffer data) throws AnalysisException { + switch (mysqlType) { + case MYSQL_TYPE_TINY: + return new TinyIntLiteral(data.get()); + case MYSQL_TYPE_SHORT: + return new SmallIntLiteral((short) data.getChar()); + case MYSQL_TYPE_LONG: + return new IntegerLiteral(data.getInt()); + case MYSQL_TYPE_LONGLONG: + return new BigIntLiteral(data.getLong()); + case MYSQL_TYPE_FLOAT: + return new FloatLiteral(data.getFloat()); + case MYSQL_TYPE_DOUBLE: + return new DoubleLiteral(data.getDouble()); + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return handleDecimalLiteral(data); + case MYSQL_TYPE_DATE: + return handleDateLiteral(data); + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_TIMESTAMP2: + return handleDateTimeLiteral(data); + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VARSTRING: + return handleStringLiteral(data); + case MYSQL_TYPE_VARCHAR: + return handleVarcharLiteral(data); + default: + throw new AnalysisException("Unsupported MySQL type: " + mysqlType); + } + } + + private static DecimalLiteral handleDecimalLiteral(ByteBuffer data) throws AnalysisException { + int len = getParmLen(data); + byte[] bytes = new byte[len]; + data.get(bytes); + try { + String value = new String(bytes); + BigDecimal v = new BigDecimal(value); + return new DecimalLiteral(v); + } catch (NumberFormatException e) { + throw new AnalysisException("Invalid decimal literal", e); + } + } + + private static DateLiteral handleDateLiteral(ByteBuffer data) { + int len = getParmLen(data); + if (len >= 4) { + int year = (int) data.getChar(); + int month = (int) data.get(); + int day = (int) data.get(); + return new DateLiteral(year, month, day); Review Comment: done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org