This is an automated email from the ASF dual-hosted git repository. xuyang pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push: new c5bb0e3a211 [bug](prepared statement) fix prepared statement throw exception when inserting null value (#36484) c5bb0e3a211 is described below commit c5bb0e3a211842d2e498834410cc3581ffe05cde Author: xy720 <22125576+xy...@users.noreply.github.com> AuthorDate: Thu Jun 20 11:31:59 2024 +0800 [bug](prepared statement) fix prepared statement throw exception when inserting null value (#36484) ## Proposed changes bp #36426 <!--Describe your changes.--> --- .../org/apache/doris/analysis/PlaceHolderExpr.java | 19 ++++++++++++++----- .../java/org/apache/doris/analysis/PrepareStmt.java | 1 + .../main/java/org/apache/doris/planner/ScanNode.java | 4 +++- .../apache/doris/rewrite/RewriteInPredicateRule.java | 7 ++++++- regression-test/data/insert_p0/prepare_insert.out | 1 + .../suites/insert_p0/prepare_insert.groovy | 18 ++++++++++++++++-- 6 files changed, 41 insertions(+), 9 deletions(-) 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 28d4ce51d55..d6fc6e8e96e 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 @@ -59,6 +59,20 @@ public class PlaceHolderExpr extends LiteralExpr { this.type = literal.getType(); } + public LiteralExpr getLiteral() { + return lExpr; + } + + @Override + protected void analysisDone() { + if (lExpr != null && !lExpr.isAnalyzed) { + lExpr.analysisDone(); + } + if (!isAnalyzed) { + super.analysisDone(); + } + } + public LiteralExpr createLiteralFromType() throws AnalysisException { Preconditions.checkState(mysqlTypeCode > 0); return LiteralExpr.getLiteralByMysqlType(mysqlTypeCode, isUnsigned()); @@ -135,11 +149,6 @@ 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 { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/PrepareStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/PrepareStmt.java index 90da98c14f4..1c7b5459979 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/PrepareStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/PrepareStmt.java @@ -268,6 +268,7 @@ public class PrepareStmt extends StatementBase { } for (int i = 0; i < values.size(); ++i) { inner.getPlaceHolders().get(i).setLiteral(values.get(i)); + inner.getPlaceHolders().get(i).analysisDone(); } if (!values.isEmpty()) { if (LOG.isDebugEnabled()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java index a72b7328c33..8fc9da0260e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java @@ -29,6 +29,7 @@ import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.IsNullPredicate; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.NullLiteral; +import org.apache.doris.analysis.PlaceHolderExpr; import org.apache.doris.analysis.PredicateUtils; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotId; @@ -399,7 +400,8 @@ public abstract class ScanNode extends PlanNode implements SplitGenerator { if (null == partitionColumnFilter) { partitionColumnFilter = new PartitionColumnFilter(); } - LiteralExpr literal = (LiteralExpr) slotBinding; + LiteralExpr literal = slotBinding instanceof PlaceHolderExpr + ? ((PlaceHolderExpr) slotBinding).getLiteral() : (LiteralExpr) slotBinding; BinaryPredicate.Operator op = binPredicate.getOp(); if (!binPredicate.slotIsLeft()) { op = op.commutative(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/RewriteInPredicateRule.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/RewriteInPredicateRule.java index c04ff432961..3541690d002 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/RewriteInPredicateRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/RewriteInPredicateRule.java @@ -23,6 +23,7 @@ import org.apache.doris.analysis.CastExpr; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.analysis.PlaceHolderExpr; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.Subquery; import org.apache.doris.catalog.Type; @@ -114,7 +115,11 @@ public class RewriteInPredicateRule implements ExprRewriteRule { // For example, 2.1 is converted to 2; // 3. childExpr is precisely converted to column type. For example, 2.0 is converted to 2. // In cases 1 and 2 above, childExpr should be discarded. - LiteralExpr newExpr = (LiteralExpr) childExpr.castTo(columnType); + Expr tmpExpr = childExpr.castTo(columnType); + if (tmpExpr instanceof CastExpr && tmpExpr.getChild(0) instanceof PlaceHolderExpr) { + tmpExpr = ((PlaceHolderExpr) tmpExpr.getChild(0)).getLiteral().castTo(columnType); + } + LiteralExpr newExpr = (LiteralExpr) tmpExpr; if (childExpr.compareLiteral(newExpr) == 0) { isCast = true; newInList.add(newExpr); diff --git a/regression-test/data/insert_p0/prepare_insert.out b/regression-test/data/insert_p0/prepare_insert.out index a84bd02040e..f535890c5b8 100644 --- a/regression-test/data/insert_p0/prepare_insert.out +++ b/regression-test/data/insert_p0/prepare_insert.out @@ -1,5 +1,6 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !sql -- +\N \N \N 1 a 90 2 ab 91 3 abc 92 diff --git a/regression-test/suites/insert_p0/prepare_insert.groovy b/regression-test/suites/insert_p0/prepare_insert.groovy index 305758170d7..235adf03c1d 100644 --- a/regression-test/suites/insert_p0/prepare_insert.groovy +++ b/regression-test/suites/insert_p0/prepare_insert.groovy @@ -34,7 +34,7 @@ suite("prepare_insert") { sql """ DROP TABLE IF EXISTS ${tableName} """ sql """ CREATE TABLE ${tableName} ( - `id` int(11) NOT NULL, + `id` int(11) NULL, `name` varchar(50) NULL, `score` int(11) NULL DEFAULT "-1" ) ENGINE=OLAP @@ -141,6 +141,20 @@ suite("prepare_insert") { stmt.close() } + // insert with null + result1 = connect(user = user, password = password, url = url) { + def stmt = prepareStatement "insert into ${tableName} values(?, ?, ?)" + assertEquals(com.mysql.cj.jdbc.ServerPreparedStatement, stmt.class) + stmt.setNull(1, java.sql.Types.INTEGER) + stmt.setNull(2, java.sql.Types.VARCHAR) + stmt.setNull(3, java.sql.Types.INTEGER) + def result = stmt.execute() + logger.info("result: ${result}") + getServerInfo(stmt) + + stmt.close() + } + // insert with label def label = "insert_" + System.currentTimeMillis() result1 = connect(user = user, password = password, url = url) { @@ -238,4 +252,4 @@ suite("prepare_insert") { } qt_sql """ select * from ${tableName} order by id, name, score """ -} \ No newline at end of file +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org